[powermock] 03/04: Imported Upstream version 1.6.5
Emmanuel Bourg
ebourg-guest at moszumanska.debian.org
Tue Jun 28 22:02:54 UTC 2016
This is an automated email from the git hooks/post-receive script.
ebourg-guest pushed a commit to annotated tag debian/1.6.5-1
in repository powermock.
commit 2439dee53ab2d431dc19a5f44a5c1a672cfedcbc
Author: Emmanuel Bourg <ebourg at apache.org>
Date: Tue Jun 28 16:21:12 2016 +0200
Imported Upstream version 1.6.5
---
.github/ISSUE_TEMPLATE.md | 29 +
.gitignore | 9 +
.travis.yml | 11 +
LICENSE.txt | 202 ++
README.md | 69 +
api/easymock/pom.xml | 32 +
.../api/easymock/EasyMockConfiguration.java | 83 +
.../java/org/powermock/api/easymock/PowerMock.java | 2125 ++++++++++++++
.../powermock/api/easymock/annotation/Mock.java | 80 +
.../api/easymock/annotation/MockNice.java | 67 +
.../api/easymock/annotation/MockStrict.java | 66 +
.../EasyMockMethodInvocationControl.java | 152 +
.../NewInvocationControlAssertionError.java | 23 +
.../NewInvocationControlImpl.java | 113 +
.../internal/mockstrategy/MockStrategy.java | 9 +
.../impl/AbstractMockStrategyBase.java | 27 +
.../mockstrategy/impl/DefaultMockStrategy.java | 10 +
.../mockstrategy/impl/NiceMockStrategy.java | 10 +
.../mockstrategy/impl/StrictMockStrategy.java | 10 +
.../AbstractEasyMockLogPolicyBase.java | 99 +
.../api/easymock/mockpolicies/JclMockPolicy.java | 62 +
.../api/easymock/mockpolicies/Log4jMockPolicy.java | 62 +
.../api/easymock/mockpolicies/Slf4jMockPolicy.java | 58 +
.../powermocklistener/AnnotationEnabler.java | 32 +
.../agent/JavaAgentFrameworkRegisterImpl.java | 36 +
.../api/extension/listener/AnnotationEnabler.java | 83 +
.../listener/AnnotationGlobalMetadata.java | 69 +
.../extension/listener/AnnotationMockCreator.java | 27 +
.../listener/AnnotationMockCreatorFactory.java | 56 +
.../extension/listener/AnnotationMockMetadata.java | 114 +
.../extension/listener/AnnotationMockScanner.java | 58 +
.../listener/EasyMockAnnotationSupport.java | 135 +
.../extension/listener/TestSubjectInjector.java | 153 +
.../proxyframework/ProxyFrameworkImpl.java | 33 +
.../MockingFrameworkReporterFactoryImpl.java | 48 +
api/mockito-common/pom.xml | 40 +
.../agent/JavaAgentFrameworkRegisterImpl.java | 43 +
.../MockingFrameworkReporterFactoryImpl.java | 88 +
.../api/mockito/ClassNotPreparedException.java | 12 +
.../reporter/MockitoPowerMockReporter.java | 36 +
.../internal/mockcreation/AbstractMockCreator.java | 24 +
.../internal/mockcreation/MockTypeValidator.java | 8 +
.../mockcreation/MockTypeValidatorFactory.java | 92 +
api/mockito/pom.xml | 37 +
.../api/extension/listener/AnnotationEnabler.java | 141 +
.../proxyframework/ProxyFrameworkImpl.java | 54 +
.../org/powermock/api/mockito/PowerMockito.java | 799 ++++++
.../expectation/ConstructorExpectationSetup.java | 20 +
.../mockito/expectation/PowerMockitoStubber.java | 209 ++
.../expectation/PrivatelyExpectedArguments.java | 21 +
.../api/mockito/expectation/WithAnyArguments.java | 24 +
.../mockito/expectation/WithExpectedArguments.java | 24 +
.../expectation/WithExpectedParameterTypes.java | 22 +
.../WithOrWithoutExpectedArguments.java | 19 +
.../expectation/WithoutExpectedArguments.java | 24 +
.../api/mockito/internal/PowerMockitoCore.java | 55 +
.../PowerMockitoInjectingAnnotationEngine.java | 37 +
.../PowerMockitoSpyAnnotationEngine.java | 66 +
.../exceptions/StackTraceCleanerProvider.java | 15 +
.../ConstructorAwareExpectationSetup.java | 50 +
.../DefaultConstructorExpectationSetup.java | 117 +
.../expectation/DefaultMethodExpectationSetup.java | 63 +
.../DefaultPrivatelyExpectedArguments.java | 51 +
.../DelegatingToConstructorsOngoingStubbing.java | 151 +
.../expectation/PowerMockitoStubberImpl.java | 134 +
.../InvocationControlAssertionError.java | 157 ++
.../invocation/MockitoMethodInvocationControl.java | 338 +++
.../invocation/MockitoNewInvocationControl.java | 121 +
.../invocation/PowerMockMatchersBinder.java | 42 +
.../internal/invocation/ToStringGenerator.java | 44 +
.../mockito/internal/mockcreation/MockCreator.java | 189 ++
.../internal/mockcreation/MockitoStateCleaner.java | 30 +
.../PowerMockMethodInterceptorFilter.java | 29 +
.../mockito/internal/mockmaker/PowerMockMaker.java | 109 +
.../internal/stubbing/answers/ChainReturns.java | 39 +
.../DefaultConstructorArgumentsVerfication.java | 61 +
.../DefaultPrivateMethodVerification.java | 75 +
.../StaticMockAwareVerificationMode.java | 62 +
.../verification/VerifyNoMoreInteractions.java | 62 +
.../api/mockito/mockpolicies/Slf4jMockPolicy.java | 103 +
.../powermocklistener/AnnotationEnabler.java | 28 +
.../repackaged/AcrossJVMSerializationFeature.java | 426 +++
.../api/mockito/repackaged/CGLIBHacker.java | 42 +
.../api/mockito/repackaged/CglibMockMaker.java | 54 +
.../api/mockito/repackaged/ClassImposterizer.java | 161 ++
.../repackaged/DelegatingMockitoMethodProxy.java | 22 +
.../repackaged/MethodInterceptorFilter.java | 84 +
.../api/mockito/repackaged/Mockito-LICENSE.txt | 21 +
.../mockito/repackaged/MockitoNamingPolicy.java | 17 +
.../repackaged/SerializableMockitoMethodProxy.java | 45 +
.../api/mockito/repackaged/SerializableNoOp.java | 20 +
.../api/mockito/repackaged/package-info.java | 4 +
.../ConstructorArgumentsVerification.java | 23 +
.../verification/PrivateMethodVerification.java | 46 +
.../WithOrWithoutVerifiedArguments.java | 19 +
.../verification/WithVerifiedArguments.java | 23 +
.../verification/WithoutVerifiedArguments.java | 22 +
.../org.mockito.plugins.MockMaker | 1 +
.../org.mockito.plugins.StackTraceCleanerProvider | 1 +
.../DefaultMethodExpectationSetupTest.java | 66 +
.../internal/mockcreation/MockCreatorTest.java | 43 +
.../stubbing/answers/ChainReturnsTest.java | 54 +
api/mockito2/pom.xml | 37 +
.../api/extension/listener/AnnotationEnabler.java | 130 +
.../proxyframework/ProxyFrameworkImpl.java | 55 +
.../org/powermock/api/mockito/PowerMockito.java | 800 ++++++
.../expectation/ConstructorExpectationSetup.java | 21 +
.../mockito/expectation/PowerMockitoStubber.java | 210 ++
.../expectation/PrivatelyExpectedArguments.java | 22 +
.../api/mockito/expectation/WithAnyArguments.java | 25 +
.../mockito/expectation/WithExpectedArguments.java | 25 +
.../expectation/WithExpectedParameterTypes.java | 23 +
.../WithOrWithoutExpectedArguments.java | 20 +
.../expectation/WithoutExpectedArguments.java | 25 +
.../api/mockito/internal/PowerMockitoCore.java | 56 +
.../PowerMockitoInjectingAnnotationEngine.java | 38 +
.../PowerMockitoSpyAnnotationEngine.java | 67 +
.../exceptions/StackTraceCleanerProvider.java | 32 +
.../ConstructorAwareExpectationSetup.java | 51 +
.../DefaultConstructorExpectationSetup.java | 118 +
.../expectation/DefaultMethodExpectationSetup.java | 64 +
.../DefaultPrivatelyExpectedArguments.java | 52 +
.../DelegatingToConstructorsOngoingStubbing.java | 163 ++
.../expectation/PowerMockitoStubberImpl.java | 135 +
.../InvocationControlAssertionError.java | 158 ++
.../invocation/MockitoMethodInvocationControl.java | 339 +++
.../invocation/MockitoNewInvocationControl.java | 122 +
.../invocation/PowerMockMatchersBinder.java | 74 +
.../internal/invocation/ToStringGenerator.java | 61 +
.../mockito/internal/mockcreation/MockCreator.java | 189 ++
.../internal/mockcreation/MockitoStateCleaner.java | 47 +
.../PowerMockMethodInterceptorFilter.java | 46 +
.../mockito/internal/mockmaker/PowerMockMaker.java | 115 +
.../internal/stubbing/answers/ChainReturns.java | 56 +
.../DefaultConstructorArgumentsVerfication.java | 62 +
.../DefaultPrivateMethodVerification.java | 76 +
.../StaticMockAwareVerificationMode.java | 63 +
.../verification/VerifyNoMoreInteractions.java | 63 +
.../api/mockito/mockpolicies/Slf4jMockPolicy.java | 105 +
.../powermocklistener/AnnotationEnabler.java | 29 +
.../repackaged/AcrossJVMSerializationFeature.java | 429 +++
.../api/mockito/repackaged/CGLIBHacker.java | 42 +
.../api/mockito/repackaged/CglibMockMaker.java | 72 +
.../api/mockito/repackaged/ClassImposterizer.java | 164 ++
.../repackaged/DelegatingMockitoMethodProxy.java | 21 +
.../repackaged/MethodInterceptorFilter.java | 83 +
.../api/mockito/repackaged/Mockito-LICENSE.txt | 21 +
.../mockito/repackaged/MockitoNamingPolicy.java | 17 +
.../repackaged/SerializableMockitoMethodProxy.java | 44 +
.../api/mockito/repackaged/SerializableNoOp.java | 20 +
.../mockito/repackaged/asm/AnnotationVisitor.java | 97 +
.../mockito/repackaged/asm/AnnotationWriter.java | 309 +++
.../api/mockito/repackaged/asm/Attribute.java | 254 ++
.../api/mockito/repackaged/asm/ByteVector.java | 293 ++
.../api/mockito/repackaged/asm/ClassAdapter.java | 121 +
.../api/mockito/repackaged/asm/ClassReader.java | 1996 ++++++++++++++
.../api/mockito/repackaged/asm/ClassVisitor.java | 196 ++
.../api/mockito/repackaged/asm/ClassWriter.java | 1311 +++++++++
.../powermock/api/mockito/repackaged/asm/Edge.java | 75 +
.../api/mockito/repackaged/asm/FieldVisitor.java | 64 +
.../api/mockito/repackaged/asm/FieldWriter.java | 264 ++
.../api/mockito/repackaged/asm/Frame.java | 1388 ++++++++++
.../api/mockito/repackaged/asm/Handler.java | 70 +
.../powermock/api/mockito/repackaged/asm/Item.java | 256 ++
.../api/mockito/repackaged/asm/Label.java | 518 ++++
.../api/mockito/repackaged/asm/MethodAdapter.java | 195 ++
.../api/mockito/repackaged/asm/MethodVisitor.java | 395 +++
.../api/mockito/repackaged/asm/MethodWriter.java | 2564 +++++++++++++++++
.../api/mockito/repackaged/asm/Opcodes.java | 341 +++
.../powermock/api/mockito/repackaged/asm/Type.java | 794 ++++++
.../api/mockito/repackaged/asm/package.html | 117 +
.../repackaged/asm/signature/SignatureReader.java | 229 ++
.../repackaged/asm/signature/SignatureVisitor.java | 185 ++
.../repackaged/asm/signature/SignatureWriter.java | 207 ++
.../mockito/repackaged/asm/signature/package.html | 66 +
.../repackaged/asm/tree/AbstractInsnNode.java | 233 ++
.../repackaged/asm/tree/AnnotationNode.java | 191 ++
.../api/mockito/repackaged/asm/tree/ClassNode.java | 280 ++
.../mockito/repackaged/asm/tree/FieldInsnNode.java | 103 +
.../api/mockito/repackaged/asm/tree/FieldNode.java | 127 +
.../api/mockito/repackaged/asm/tree/FrameNode.java | 208 ++
.../mockito/repackaged/asm/tree/IincInsnNode.java | 77 +
.../repackaged/asm/tree/InnerClassNode.java | 101 +
.../api/mockito/repackaged/asm/tree/InsnList.java | 640 +++++
.../api/mockito/repackaged/asm/tree/InsnNode.java | 81 +
.../mockito/repackaged/asm/tree/IntInsnNode.java | 81 +
.../mockito/repackaged/asm/tree/JumpInsnNode.java | 89 +
.../api/mockito/repackaged/asm/tree/LabelNode.java | 75 +
.../mockito/repackaged/asm/tree/LdcInsnNode.java | 74 +
.../repackaged/asm/tree/LineNumberNode.java | 79 +
.../repackaged/asm/tree/LocalVariableNode.java | 115 +
.../repackaged/asm/tree/LookupSwitchInsnNode.java | 113 +
.../mockito/repackaged/asm/tree/MemberNode.java | 120 +
.../repackaged/asm/tree/MethodInsnNode.java | 104 +
.../mockito/repackaged/asm/tree/MethodNode.java | 490 ++++
.../asm/tree/MultiANewArrayInsnNode.java | 78 +
.../repackaged/asm/tree/TableSwitchInsnNode.java | 112 +
.../repackaged/asm/tree/TryCatchBlockNode.java | 94 +
.../mockito/repackaged/asm/tree/TypeInsnNode.java | 84 +
.../mockito/repackaged/asm/tree/VarInsnNode.java | 87 +
.../repackaged/asm/tree/analysis/Analyzer.java | 507 ++++
.../asm/tree/analysis/AnalyzerException.java | 56 +
.../asm/tree/analysis/BasicInterpreter.java | 321 +++
.../repackaged/asm/tree/analysis/BasicValue.java | 105 +
.../asm/tree/analysis/BasicVerifier.java | 423 +++
.../repackaged/asm/tree/analysis/Frame.java | 667 +++++
.../repackaged/asm/tree/analysis/Interpreter.java | 178 ++
.../asm/tree/analysis/SimpleVerifier.java | 284 ++
.../repackaged/asm/tree/analysis/SmallSet.java | 125 +
.../asm/tree/analysis/SourceInterpreter.java | 174 ++
.../repackaged/asm/tree/analysis/SourceValue.java | 95 +
.../repackaged/asm/tree/analysis/Subroutine.java | 93 +
.../repackaged/asm/tree/analysis/Value.java | 45 +
.../repackaged/asm/tree/analysis/package.html | 97 +
.../api/mockito/repackaged/asm/tree/package.html | 222 ++
.../mockito/repackaged/asm/util/ASMifiable.java | 53 +
.../asm/util/ASMifierAbstractVisitor.java | 222 ++
.../asm/util/ASMifierAnnotationVisitor.java | 127 +
.../repackaged/asm/util/ASMifierClassVisitor.java | 575 ++++
.../repackaged/asm/util/ASMifierFieldVisitor.java | 50 +
.../repackaged/asm/util/ASMifierMethodVisitor.java | 443 +++
.../repackaged/asm/util/AbstractVisitor.java | 202 ++
.../asm/util/CheckAnnotationAdapter.java | 132 +
.../repackaged/asm/util/CheckClassAdapter.java | 480 ++++
.../repackaged/asm/util/CheckFieldAdapter.java | 77 +
.../repackaged/asm/util/CheckMethodAdapter.java | 1325 +++++++++
.../repackaged/asm/util/CheckSignatureAdapter.java | 287 ++
.../repackaged/asm/util/TraceAbstractVisitor.java | 179 ++
.../asm/util/TraceAnnotationVisitor.java | 266 ++
.../repackaged/asm/util/TraceClassVisitor.java | 523 ++++
.../repackaged/asm/util/TraceFieldVisitor.java | 78 +
.../repackaged/asm/util/TraceMethodVisitor.java | 563 ++++
.../repackaged/asm/util/TraceSignatureVisitor.java | 300 ++
.../api/mockito/repackaged/asm/util/Traceable.java | 52 +
.../api/mockito/repackaged/asm/util/package.html | 70 +
.../mockito/repackaged/cglib/beans/BeanCopier.java | 173 ++
.../repackaged/cglib/beans/BeanGenerator.java | 139 +
.../mockito/repackaged/cglib/beans/BeanMap.java | 311 +++
.../repackaged/cglib/beans/BeanMapEmitter.java | 192 ++
.../mockito/repackaged/cglib/beans/BulkBean.java | 122 +
.../repackaged/cglib/beans/BulkBeanEmitter.java | 153 +
.../repackaged/cglib/beans/BulkBeanException.java | 30 +
.../repackaged/cglib/beans/FixedKeySet.java | 30 +
.../repackaged/cglib/beans/ImmutableBean.java | 122 +
.../cglib/core/AbstractClassGenerator.java | 235 ++
.../api/mockito/repackaged/cglib/core/Block.java | 38 +
.../repackaged/cglib/core/ClassEmitter.java | 270 ++
.../repackaged/cglib/core/ClassGenerator.java | 11 +
.../mockito/repackaged/cglib/core/ClassInfo.java | 35 +
.../repackaged/cglib/core/ClassNameReader.java | 53 +
.../mockito/repackaged/cglib/core/ClassesKey.java | 20 +
.../mockito/repackaged/cglib/core/CodeEmitter.java | 851 ++++++
.../cglib/core/CodeGenerationException.java | 21 +
.../repackaged/cglib/core/CollectionUtils.java | 70 +
.../mockito/repackaged/cglib/core/Constants.java | 56 +
.../mockito/repackaged/cglib/core/Converter.java | 9 +
.../mockito/repackaged/cglib/core/Customizer.java | 11 +
.../cglib/core/DebuggingClassWriter.java | 107 +
.../cglib/core/DefaultGeneratorStrategy.java | 29 +
.../repackaged/cglib/core/DefaultNamingPolicy.java | 45 +
.../repackaged/cglib/core/DuplicatesPredicate.java | 17 +
.../mockito/repackaged/cglib/core/EmitUtils.java | 911 ++++++
.../repackaged/cglib/core/GeneratorStrategy.java | 33 +
.../mockito/repackaged/cglib/core/KeyFactory.java | 246 ++
.../api/mockito/repackaged/cglib/core/Local.java | 26 +
.../cglib/core/LocalVariablesSorter.java | 133 +
.../mockito/repackaged/cglib/core/MethodInfo.java | 35 +
.../cglib/core/MethodInfoTransformer.java | 27 +
.../repackaged/cglib/core/MethodWrapper.java | 38 +
.../repackaged/cglib/core/NamingPolicy.java | 30 +
.../cglib/core/ObjectSwitchCallback.java | 13 +
.../mockito/repackaged/cglib/core/Predicate.java | 10 +
.../cglib/core/ProcessArrayCallback.java | 11 +
.../cglib/core/ProcessSwitchCallback.java | 12 +
.../repackaged/cglib/core/ReflectUtils.java | 462 ++++
.../cglib/core/RejectModifierPredicate.java | 19 +
.../mockito/repackaged/cglib/core/Signature.java | 62 +
.../mockito/repackaged/cglib/core/TinyBitSet.java | 68 +
.../mockito/repackaged/cglib/core/Transformer.java | 9 +
.../mockito/repackaged/cglib/core/TypeUtils.java | 412 +++
.../repackaged/cglib/core/VisibilityPredicate.java | 34 +
.../mockito/repackaged/cglib/proxy/Callback.java | 18 +
.../repackaged/cglib/proxy/CallbackFilter.java | 34 +
.../repackaged/cglib/proxy/CallbackGenerator.java | 28 +
.../repackaged/cglib/proxy/CallbackHelper.java | 91 +
.../repackaged/cglib/proxy/CallbackInfo.java | 90 +
.../mockito/repackaged/cglib/proxy/Dispatcher.java | 19 +
.../cglib/proxy/DispatcherGenerator.java | 60 +
.../mockito/repackaged/cglib/proxy/Enhancer.java | 1059 +++++++
.../mockito/repackaged/cglib/proxy/Factory.java | 68 +
.../mockito/repackaged/cglib/proxy/FixedValue.java | 24 +
.../cglib/proxy/FixedValueGenerator.java | 37 +
.../repackaged/cglib/proxy/InterfaceMaker.java | 114 +
.../repackaged/cglib/proxy/InvocationHandler.java | 24 +
.../cglib/proxy/InvocationHandlerGenerator.java | 62 +
.../mockito/repackaged/cglib/proxy/LazyLoader.java | 19 +
.../cglib/proxy/LazyLoaderGenerator.java | 86 +
.../repackaged/cglib/proxy/MethodInterceptor.java | 31 +
.../cglib/proxy/MethodInterceptorGenerator.java | 243 ++
.../repackaged/cglib/proxy/MethodProxy.java | 209 ++
.../api/mockito/repackaged/cglib/proxy/Mixin.java | 230 ++
.../repackaged/cglib/proxy/MixinBeanEmitter.java | 28 +
.../repackaged/cglib/proxy/MixinEmitter.java | 88 +
.../cglib/proxy/MixinEverythingEmitter.java | 41 +
.../api/mockito/repackaged/cglib/proxy/NoOp.java | 17 +
.../repackaged/cglib/proxy/NoOpGenerator.java | 37 +
.../api/mockito/repackaged/cglib/proxy/Proxy.java | 91 +
.../repackaged/cglib/proxy/ProxyRefDispatcher.java | 20 +
.../cglib/proxy/UndeclaredThrowableException.java | 25 +
.../cglib/reflect/ConstructorDelegate.java | 116 +
.../repackaged/cglib/reflect/FastClass.java | 195 ++
.../repackaged/cglib/reflect/FastClassEmitter.java | 236 ++
.../repackaged/cglib/reflect/FastConstructor.java | 35 +
.../repackaged/cglib/reflect/FastMember.java | 54 +
.../repackaged/cglib/reflect/FastMethod.java | 48 +
.../repackaged/cglib/reflect/MethodDelegate.java | 257 ++
.../cglib/reflect/MulticastDelegate.java | 170 ++
.../transform/AbstractClassFilterTransformer.java | 78 +
.../cglib/transform/AbstractClassLoader.java | 107 +
.../cglib/transform/AbstractClassTransformer.java | 18 +
.../cglib/transform/AnnotationVisitorTee.java | 48 +
.../cglib/transform/ClassEmitterTransformer.java | 11 +
.../repackaged/cglib/transform/ClassFilter.java | 16 +
.../cglib/transform/ClassFilterTransformer.java | 18 +
.../cglib/transform/ClassReaderGenerator.java | 30 +
.../cglib/transform/ClassTransformer.java | 11 +
.../cglib/transform/ClassTransformerChain.java | 46 +
.../cglib/transform/ClassTransformerFactory.java | 9 +
.../cglib/transform/ClassTransformerTee.java | 21 +
.../cglib/transform/ClassVisitorTee.java | 90 +
.../cglib/transform/FieldVisitorTee.java | 34 +
.../repackaged/cglib/transform/MethodFilter.java | 10 +
.../cglib/transform/MethodFilterTransformer.java | 33 +
.../cglib/transform/MethodVisitorTee.java | 143 +
.../transform/TransformingClassGenerator.java | 23 +
.../cglib/transform/TransformingClassLoader.java | 22 +
.../impl/AbstractInterceptFieldCallback.java | 31 +
.../transform/impl/AccessFieldTransformer.java | 53 +
.../transform/impl/AddDelegateTransformer.java | 113 +
.../cglib/transform/impl/AddInitTransformer.java | 50 +
.../transform/impl/AddPropertyTransformer.java | 38 +
.../transform/impl/AddStaticInitTransformer.java | 44 +
.../cglib/transform/impl/FieldProvider.java | 23 +
.../transform/impl/FieldProviderTransformer.java | 205 ++
.../transform/impl/InterceptFieldCallback.java | 31 +
.../transform/impl/InterceptFieldEnabled.java | 11 +
.../cglib/transform/impl/InterceptFieldFilter.java | 12 +
.../transform/impl/InterceptFieldTransformer.java | 203 ++
.../impl/UndeclaredThrowableStrategy.java | 45 +
.../impl/UndeclaredThrowableTransformer.java | 53 +
.../repackaged/cglib/util/ParallelSorter.java | 283 ++
.../cglib/util/ParallelSorterEmitter.java | 93 +
.../repackaged/cglib/util/SorterTemplate.java | 160 ++
.../repackaged/cglib/util/StringSwitcher.java | 154 ++
.../api/mockito/repackaged/package-info.java | 9 +
.../powermock/api/mockito/repackaged/package.html | 6 +
.../ConstructorArgumentsVerification.java | 24 +
.../verification/PrivateMethodVerification.java | 47 +
.../WithOrWithoutVerifiedArguments.java | 20 +
.../verification/WithVerifiedArguments.java | 24 +
.../verification/WithoutVerifiedArguments.java | 23 +
.../org.mockito.plugins.MockMaker | 1 +
.../org.mockito.plugins.StackTraceCleanerProvider | 1 +
.../DefaultMethodExpectationSetupTest.java | 66 +
.../internal/mockcreation/MockCreatorTest.java | 43 +
.../stubbing/answers/ChainReturnsTest.java | 54 +
api/pom.xml | 25 +
api/support/pom.xml | 33 +
.../AbstractMockingFrameworkReporterFactory.java | 56 +
.../org/powermock/api/support/ClassLoaderUtil.java | 71 +
.../org/powermock/api/support/MethodProxy.java | 65 +
.../api/support/SafeExceptionRethrower.java | 29 +
.../java/org/powermock/api/support/Stubber.java | 57 +
.../org/powermock/api/support/SuppressCode.java | 245 ++
.../support/membermodification/MemberMatcher.java | 361 +++
.../support/membermodification/MemberModifier.java | 114 +
.../strategy/ClassReplaceStrategy.java | 32 +
.../strategy/MethodReplaceStrategy.java | 44 +
.../strategy/MethodStubStrategy.java | 47 +
.../strategy/impl/MethodReplaceStrategyImpl.java | 75 +
.../strategy/impl/MethodStubStrategyImpl.java | 58 +
changelog.txt | 605 ++++
classloading/classloading-base/pom.xml | 40 +
.../classloading/AbstractClassloaderExecutor.java | 94 +
.../classloading/ClassloaderExecutor.java | 30 +
.../classloading/SingleClassloaderExecutor.java | 70 +
.../powermock/classloading/spi/DeepClonerSPI.java | 8 +
.../org/powermock/classloading/spi/DoNotClone.java | 27 +
classloading/classloading-objenesis/pom.xml | 28 +
.../org/powermock/classloading/DeepCloner.java | 382 +++
.../ObjenesisClassloaderExecutorTest.java | 303 ++
.../classloading/ObjenesisDeepClonerTest.java | 123 +
.../powermock/classloading/classes/MyArgument.java | 59 +
.../powermock/classloading/classes/MyClass.java | 32 +
.../classloading/classes/MyCollectionHolder.java | 32 +
.../powermock/classloading/classes/MyEnum.java | 23 +
.../classloading/classes/MyEnumHolder.java | 30 +
.../classes/MyHierarchicalFieldHolder.java | 24 +
.../MyHierarchicalOverloadedFieldHolder.java | 25 +
.../classloading/classes/MyIntegerHolder.java | 30 +
.../classes/MyPrimitiveArrayHolder.java | 30 +
.../classes/MyReferenceFieldHolder.java | 31 +
.../classloading/classes/MyReturnValue.java | 33 +
.../classes/MyStaticFinalArgumentHolder.java | 25 +
.../classes/MyStaticFinalNumberHolder.java | 25 +
.../classes/MyStaticFinalPrimitiveHolder.java | 25 +
.../classes/ReflectionMethodInvoker.java | 37 +
classloading/classloading-xstream/pom.xml | 32 +
.../org/powermock/classloading/DeepCloner.java | 57 +
.../XStreamClassloaderExecutorTest.java | 300 ++
.../classloading/XStreamDeepClonerTest.java | 113 +
.../powermock/classloading/classes/MyArgument.java | 59 +
.../powermock/classloading/classes/MyClass.java | 32 +
.../classloading/classes/MyCollectionHolder.java | 32 +
.../powermock/classloading/classes/MyEnum.java | 23 +
.../classloading/classes/MyEnumHolder.java | 30 +
.../classes/MyHierarchicalFieldHolder.java | 24 +
.../MyHierarchicalOverloadedFieldHolder.java | 25 +
.../classloading/classes/MyIntegerHolder.java | 30 +
.../classes/MyPrimitiveArrayHolder.java | 30 +
.../classes/MyReferenceFieldHolder.java | 31 +
.../classloading/classes/MyReturnValue.java | 33 +
.../classes/MyStaticFinalArgumentHolder.java | 25 +
.../classes/MyStaticFinalNumberHolder.java | 25 +
.../classes/MyStaticFinalPrimitiveHolder.java | 25 +
.../classes/ReflectionMethodInvoker.java | 37 +
classloading/pom.xml | 23 +
core/pom.xml | 59 +
.../main/java/org/powermock/core/ClassLocator.java | 22 +
.../org/powermock/core/ClassReplicaCreator.java | 199 ++
.../org/powermock/core/ConcreteClassGenerator.java | 92 +
.../powermock/core/DefaultFieldValueGenerator.java | 111 +
.../java/org/powermock/core/IdentityHashSet.java | 59 +
.../org/powermock/core/IndicateReloadClass.java | 20 +
core/src/main/java/org/powermock/core/ListMap.java | 151 +
.../main/java/org/powermock/core/MockGateway.java | 274 ++
.../java/org/powermock/core/MockRepository.java | 390 +++
.../java/org/powermock/core/PowerMockUtils.java | 64 +
.../java/org/powermock/core/WildcardMatcher.java | 102 +
.../core/agent/JavaAgentClassRegister.java | 44 +
.../core/agent/JavaAgentFrameworkRegister.java | 38 +
.../agent/JavaAgentFrameworkRegisterFactory.java | 56 +
.../core/classloader/ClassPathAdjuster.java | 29 +
.../classloader/DeferSupportingClassLoader.java | 175 ++
.../core/classloader/JavaAssistClassMarker.java | 31 +
.../classloader/JavaAssistClassMarkerFactory.java | 54 +
.../core/classloader/MockClassLoader.java | 320 +++
.../core/classloader/MockClassLoaderBuilder.java | 63 +
.../core/classloader/MockClassLoaderBuilders.java | 29 +
.../core/classloader/PowerMockModified.java | 25 +
.../core/classloader/annotations/Mock.java | 82 +
.../core/classloader/annotations/MockPolicy.java | 45 +
.../classloader/annotations/PowerMockIgnore.java | 52 +
.../classloader/annotations/PowerMockListener.java | 35 +
.../annotations/PrepareEverythingForTest.java | 41 +
.../classloader/annotations/PrepareForTest.java | 79 +
.../annotations/PrepareOnlyThisForTest.java | 69 +
.../SuppressStaticInitializationFor.java | 38 +
.../annotations/UseClassPathAdjuster.java | 33 +
.../core/reporter/MockingFrameworkReporter.java | 36 +
.../reporter/MockingFrameworkReporterFactory.java | 24 +
.../powermock/core/reporter/PowerMockReporter.java | 26 +
.../core/reporter/PowerMockReporterFactory.java | 28 +
.../org/powermock/core/spi/DefaultBehavior.java | 58 +
.../core/spi/MethodInvocationControl.java | 41 +
.../powermock/core/spi/NewInvocationControl.java | 38 +
.../org/powermock/core/spi/PowerMockPolicy.java | 65 +
.../powermock/core/spi/PowerMockTestListener.java | 87 +
.../spi/listener/AnnotationEnablerListener.java | 28 +
.../support/AbstractPowerMockTestListenerBase.java | 58 +
.../core/spi/support/InvocationSubstitute.java | 31 +
.../org/powermock/core/spi/testresult/Result.java | 20 +
.../core/spi/testresult/TestMethodResult.java | 21 +
.../core/spi/testresult/TestSuiteResult.java | 29 +
.../spi/testresult/impl/TestMethodResultImpl.java | 39 +
.../spi/testresult/impl/TestSuiteResultImpl.java | 76 +
.../core/testlisteners/FieldDefaulter.java | 41 +
.../GlobalNotificationBuildSupport.java | 110 +
.../core/transformers/MockTransformer.java | 39 +
.../core/transformers/TransformStrategy.java | 21 +
.../impl/AbstractMainMockTransformer.java | 439 +++
.../transformers/impl/ClassMockTransformer.java | 73 +
.../impl/InterfaceMockTransformer.java | 67 +
.../core/transformers/impl/Primitives.java | 55 +
.../transformers/impl/TestClassTransformer.java | 342 +++
.../MockPolicyClassLoadingSettings.java | 75 +
.../MockPolicyInterceptionSettings.java | 170 ++
.../impl/MockPolicyClassLoadingSettingsImpl.java | 90 +
.../impl/MockPolicyInterceptionSettingsImpl.java | 156 ++
.../mockpolicies/support/LogPolicySupport.java | 73 +
.../org/powermock/tests/utils/ArrayMerger.java | 27 +
.../tests/utils/IgnorePackagesExtractor.java | 26 +
.../main/java/org/powermock/tests/utils/Keys.java | 41 +
.../tests/utils/MockPolicyInitializer.java | 59 +
.../tests/utils/PowerMockTestNotifier.java | 64 +
.../tests/utils/RunnerTestSuiteChunker.java | 43 +
.../java/org/powermock/tests/utils/TestChunk.java | 32 +
.../tests/utils/TestClassesExtractor.java | 29 +
.../powermock/tests/utils/TestSuiteChunker.java | 72 +
.../impl/AbstractCommonTestSuiteChunkerImpl.java | 268 ++
.../utils/impl/AbstractTestClassExtractor.java | 106 +
.../utils/impl/AbstractTestSuiteChunkerImpl.java | 197 ++
.../tests/utils/impl/ArrayMergerImpl.java | 56 +
.../tests/utils/impl/MockClassLoaderFactory.java | 127 +
.../utils/impl/MockPolicyInitializerImpl.java | 229 ++
.../impl/PowerMockIgnorePackagesExtractorImpl.java | 51 +
.../utils/impl/PowerMockTestNotifierImpl.java | 125 +
.../utils/impl/PrepareForTestExtractorImpl.java | 129 +
.../StaticConstructorSuppressExtractorImpl.java | 56 +
.../powermock/tests/utils/impl/TestCaseEntry.java | 43 +
.../powermock/tests/utils/impl/TestChunkImpl.java | 68 +
.../main/java/org/powermock/utils/ArrayUtil.java | 55 +
.../java/org/powermock/utils/StringJoiner.java | 42 +
.../java/org/powermock/WildcardMatcherTest.java | 54 +
.../powermock/core/classloader/Collaborator.java | 25 +
.../core/classloader/HardToTransform.java | 53 +
.../core/classloader/MockClassLoaderTest.java | 268 ++
.../classloader/ResourcePrefixClassLoader.java | 26 +
.../GlobalNotificationBuildSupportTest.java | 131 +
.../impl/ClassMockTransformerTest.java | 114 +
.../impl/TestClassTransformerTest.java | 130 +
.../core/transformers/impl/TestPrimitives.java | 55 +
.../PowerMockIgnorePackagesExtractorImplTest.java | 55 +
.../impl/PrepareForTestExtractorImplTest.java | 88 +
.../test/support/ClassWithLargeMethods.java | 64 +
.../support/MainMockTransformerTestSupport.java | 60 +
.../core/classloader/foo/bar/baz/test.txt | 1 +
examples/AbstractFactory/pom.xml | 41 +
.../java/powermock/examples/MyServiceUser.java | 47 +
.../dependencymanagement/DependencyManager.java | 45 +
.../java/powermock/examples/domain/Person.java | 95 +
.../java/powermock/examples/service/MyService.java | 26 +
.../examples/service/impl/MyServiceImpl.java | 33 +
.../java/powermock/examples/MyServiceUserTest.java | 108 +
examples/ApacheCLIExample/pom.xml | 40 +
.../powermock/examples/apachecli/OptionUser.java | 36 +
.../examples/apachecli/OptionUserTest.java | 59 +
examples/ApacheMina/pom.xml | 52 +
.../socket/nio/PrepareForTestAnnotationTest.java | 40 +
.../nio/PrepareOnlyThisForTestAnnotationTest.java | 49 +
examples/DocumentationExamples/pom.xml | 56 +
.../examples/annotationbased/SomeService.java | 38 +
.../examples/annotationbased/dao/SomeDao.java | 28 +
.../examples/bypassencapsulation/ReportDao.java | 41 +
.../bypassencapsulation/ReportGenerator.java | 36 +
.../bypassencapsulation/ServiceHolder.java | 36 +
.../bypassencapsulation/nontest/Cache.java | 26 +
.../bypassencapsulation/nontest/Injectable.java | 30 +
.../bypassencapsulation/nontest/Report.java | 57 +
.../nontest/ReportTemplateService.java | 34 +
.../examples/finalmocking/StateFormatter.java | 40 +
.../examples/finalmocking/StateHolder.java | 42 +
.../examples/mockpolicy/DependencyUser.java | 29 +
.../examples/mockpolicy/nontest/Dependency.java | 34 +
.../mockpolicy/nontest/domain/DataObject.java | 62 +
.../mockpolicy/policy/MyCustomMockPolicy.java | 52 +
.../examples/newmocking/PersistenceManager.java | 34 +
.../examples/partialmocking/EntityManager.java | 10 +
.../powermock/examples/partialmocking/Status.java | 7 +
.../examples/partialmocking/StatusSender.java | 24 +
.../examples/privatemocking/DataService.java | 52 +
.../examples/staticmocking/IdGenerator.java | 29 +
.../examples/staticmocking/ServiceRegistrator.java | 34 +
.../examples/suppress/constructor/EvilParent.java | 26 +
.../constructor/ExampleWithEvilConstructor.java | 34 +
.../constructor/ExampleWithEvilParent.java | 32 +
.../constructorhierarchy/EvilGrandParent.java | 27 +
.../suppress/constructorhierarchy/EvilParent.java | 27 +
.../ExampleWithEvilParentAndEvilGrandParent.java | 32 +
.../suppress/method/ExampleWithEvilMethod.java | 37 +
.../ExampleWithEvilStaticInitializer.java | 37 +
.../annotationbased/UsingMockAnnotationTest.java | 58 +
.../UsingMockNiceAnnotationTest.java | 55 +
...MockNiceAnnotationToCreateAPartialMockTest.java | 57 +
.../UsingMockStrictAnnotationTest.java | 74 +
.../bypassencapsulation/ReportDaoTest.java | 106 +
.../bypassencapsulation/ReportGeneratorTest.java | 69 +
.../bypassencapsulation/ServiceHolderTest.java | 71 +
.../examples/finalmocking/StateFormatterTest.java | 69 +
.../examples/mockpolicy/DependencyUserTest.java | 39 +
.../mockpolicy/SeveralMockPolicyMethodsTest.java | 56 +
.../newmocking/PersistenceManagerTest.java | 90 +
...stenceManagerWithReplayAllAndVerifyAllTest.java | 111 +
.../examples/partialmocking/StatusSenderTest.java | 51 +
.../examples/privatemocking/DataServiceTest.java | 86 +
.../staticmocking/ServiceRegistratorTest.java | 63 +
.../ExampleWithEvilConstructorTest.java | 40 +
.../constructor/ExampleWithEvilParentTest.java | 48 +
...xampleWithEvilParentAndEvilGrandParentTest.java | 55 +
.../suppress/method/ExampleWithEvilMethodTest.java | 42 +
.../ExampleWithEvilStaticInitializerTest.java | 39 +
examples/HamcrestExample/pom.xml | 46 +
.../org/powermock/hamcrest/HamcrestExample.java | 12 +
.../powermock/hamcrest/HamcrestExampleTest.java | 21 +
examples/SignedMocking/pom.xml | 108 +
.../org/powermock/examples/AcegiSecurityUser.java | 22 +
.../powermock/examples/AcegiSecurityUserTest.java | 36 +
examples/byte-buddy-easymock/pom.xml | 40 +
.../examples/bytebuddy/easymock/SampleClass.java | 20 +
.../easymock/ByteBuddyWithPowerMockTest.java | 69 +
examples/byte-buddy-mockito/pom.xml | 42 +
.../examples/bytebuddy/mockito/SampleClass.java | 20 +
.../mockito/ByteBuddyWithPowerMockitoTest.java | 76 +
examples/dom4j/pom.xml | 45 +
.../dom4j/AbstractXMLRequestCreatorBase.java | 103 +
.../org/powermock/examples/dom4j/XMLProtocol.java | 31 +
.../dom4j/AbstractXMLRequestCreatorBaseTest.java | 148 +
examples/easymock31/pom.xml | 48 +
.../org/powermock/examples/easymock31/Greeter.java | 38 +
.../org/powermock/examples/easymock31/Logger.java | 36 +
.../examples/easymock31/SimpleConfig.java | 39 +
.../powermock/examples/easymock31/GreeterTest.java | 68 +
examples/java8/pom.xml | 88 +
.../demo/org/powermock/examples/SimpleOps.java | 25 +
.../demo/org/powermock/examples/SimpleOpsTest.java | 38 +
examples/jcl/pom.xml | 69 +
.../main/java/org/powermock/examples/JclUser.java | 13 +
.../java/org/powermock/examples/JclUserTest.java | 36 +
examples/jdom/pom.xml | 40 +
.../src/main/java/examples/jdom/StaticClass.java | 23 +
.../java/examples/jdom/StaticWithJdomTest.java | 54 +
examples/jmock/pom.xml | 67 +
.../examples/jmock/ClassWithStaticMethod.java | 27 +
.../java/powermock/examples/jmock/FinalClass.java | 27 +
.../powermock/examples/jmock/JMockExample.java | 32 +
.../examples/jmock/JMockFinalClassTest.java | 64 +
.../examples/jmock/JMockStaticMethodTest.java | 70 +
examples/log4j/pom.xml | 64 +
.../demo/org/powermock/examples/Log4jUser.java | 15 +
.../org/powermock/examples/Log4jUserParent.java | 7 +
.../demo/org/powermock/examples/Log4jUserTest.java | 40 +
examples/pom.xml | 63 +
examples/simple/pom.xml | 45 +
.../org/powermock/examples/simple/Greeter.java | 38 +
.../demo/org/powermock/examples/simple/Logger.java | 36 +
.../powermock/examples/simple/SimpleConfig.java | 39 +
.../simple/src/main/java/simpleConfig.properties | 2 +
.../org/powermock/examples/simple/GreeterTest.java | 80 +
.../org/powermock/examples/simple/LoggerTest.java | 68 +
examples/slf4j-mockito/pom.xml | 59 +
.../demo/org/powermock/examples/Slf4jUser.java | 13 +
.../src/main/resources/log4j.properties | 8 +
.../demo/org/powermock/examples/Slf4jUserTest.java | 29 +
examples/slf4j-noimpl/pom.xml | 49 +
.../java/demo/org/powermock/examples/SL4JUser.java | 14 +
.../java/demo/org/powermock/examples/SPITest.java | 23 +
examples/slf4j/pom.xml | 50 +
.../demo/org/powermock/examples/Slf4jUser.java | 13 +
examples/slf4j/src/main/resources/log4j.properties | 8 +
.../demo/org/powermock/examples/Slf4jUserTest.java | 35 +
examples/spring-easymock/pom.xml | 86 +
.../java/powermock/examples/spring/FinalClass.java | 14 +
.../powermock/examples/spring/IdGenerator.java | 29 +
.../java/powermock/examples/spring/Message.java | 35 +
.../java/powermock/examples/spring/MyBean.java | 36 +
.../src/main/resources/example-context.xml | 28 +
.../examples/spring/mockito/SpringExampleTest.java | 84 +
.../mockito/SpringInjectFinalClassExampleTest.java | 39 +
.../SpringWithDelegateRunnerExampleTest.java | 31 +
.../spring/mockito/SpringWithRuleExampleTest.java | 35 +
examples/spring-mockito-delegate/pom.xml | 72 +
.../powermock/examples/spring/IdGenerator.java | 29 +
.../java/powermock/examples/spring/Message.java | 35 +
.../java/powermock/examples/spring/MyBean.java | 28 +
.../src/main/resources/example-context.xml | 28 +
.../examples/spring/mockito/SpringExampleTest.java | 107 +
examples/spring-mockito-xml-agent/pom.xml | 83 +
.../examples/spring/CompanyRepository.java | 45 +
.../powermock/examples/spring/IdGenerator.java | 29 +
.../java/powermock/examples/spring/Message.java | 35 +
.../java/powermock/examples/spring/MyBean.java | 37 +
.../src/main/resources/employees.xml | 15 +
.../src/main/resources/example-context.xml | 28 +
.../examples/spring/mockito/SpringExampleTest.java | 106 +
.../agent/AbstractClassTransformerTest.java | 21 +
examples/spring-mockito-xml/pom.xml | 89 +
.../examples/spring/CompanyRepository.java | 45 +
.../powermock/examples/spring/IdGenerator.java | 29 +
.../java/powermock/examples/spring/Message.java | 35 +
.../java/powermock/examples/spring/MyBean.java | 37 +
.../src/main/resources/employees.xml | 15 +
.../src/main/resources/example-context.xml | 28 +
.../examples/spring/mockito/SpringExampleTest.java | 108 +
examples/spring-mockito/pom.xml | 89 +
.../java/powermock/examples/spring/FinalClass.java | 14 +
.../powermock/examples/spring/IdGenerator.java | 29 +
.../java/powermock/examples/spring/Message.java | 35 +
.../java/powermock/examples/spring/MyBean.java | 36 +
.../src/main/resources/example-context.xml | 28 +
.../examples/spring/mockito/SpringExampleTest.java | 106 +
.../mockito/SpringInjectFinalClassExampleTest.java | 37 +
examples/tutorial/pom.xml | 103 +
examples/tutorial/readme.txt | 34 +
.../tutorial/common/annotation/Inject.java | 30 +
.../tutorial/domainmocking/EventService.java | 37 +
.../tutorial/domainmocking/PersonService.java | 37 +
.../tutorial/domainmocking/SampleService.java | 37 +
.../domainmocking/domain/BusinessMessages.java | 36 +
.../tutorial/domainmocking/domain/Person.java | 73 +
.../domain/SampleServiceException.java | 33 +
.../domainmocking/impl/SampleServiceImpl.java | 72 +
.../SampleServiceWithoutPowerMockImpl.java | 84 +
.../examples/tutorial/hellopower/HelloWorld.java | 22 +
.../examples/tutorial/hellopower/SimpleConfig.java | 47 +
.../hellopower/withoutpowermock/ConfigWrapper.java | 31 +
.../hellopower/withoutpowermock/HelloWorld.java | 31 +
.../tutorial/partialmocking/dao/ProviderDao.java | 29 +
.../partialmocking/dao/domain/Connection.java | 24 +
.../dao/domain/impl/ConnectionImpl.java | 31 +
.../dao/domain/impl/ServiceArtifact.java | 79 +
.../partialmocking/domain/DataProducer.java | 24 +
.../partialmocking/domain/ProviderArtifact.java | 64 +
.../partialmocking/domain/ServiceProducer.java | 62 +
.../partialmocking/service/ProviderService.java | 45 +
.../service/impl/ProviderServiceImpl.java | 75 +
.../ProviderServiceWithoutPowerMockImpl.java | 89 +
.../staticmocking/IServiceRegistrator.java | 47 +
.../tutorial/staticmocking/impl/IdGenerator.java | 29 +
.../staticmocking/impl/ServiceRegistrator.java | 73 +
.../ServiceRegistratorWithoutPowerMock.java | 80 +
.../tutorial/staticmocking/osgi/BundleContext.java | 26 +
.../staticmocking/osgi/ServiceRegistration.java | 26 +
.../domainmocking/impl/SampleServiceImplTest.java | 118 +
.../SampleServiceWithoutPowerMockImplTest.java | 156 ++
.../tutorial/hellopower/HelloWorldTest.java | 43 +
.../withoutpowermock/HelloWorldTest.java | 38 +
.../service/impl/ProviderServiceImplTest.java | 169 ++
.../ProviderServiceWithoutPowerMockImplTest.java | 182 ++
.../staticmocking/impl/ServiceRegistratorTest.java | 159 ++
.../withoutpowermock/ServiceRegistratorTest.java | 188 ++
.../impl/SampleServiceImplTest_Tutorial.java | 82 +
.../hellopower/HelloWorldTest_Tutorial.java | 39 +
.../impl/ProviderServiceImplTest_Tutorial.java | 106 +
.../impl/ServiceRegistratorTest_Tutorial.java | 104 +
generate_javadoc.sh | 17 +
modules/module-impl/agent/META-INF/MANIFEST.MF | 5 +
modules/module-impl/agent/jmockit-license.txt | 21 +
modules/module-impl/agent/pom.xml | 55 +
.../tools/attach/AgentInitializationException.java | 90 +
.../com/sun/tools/attach/AgentLoadException.java | 55 +
.../tools/attach/AttachNotSupportedException.java | 56 +
.../java/com/sun/tools/attach/VirtualMachine.java | 530 ++++
.../sun/tools/attach/VirtualMachineDescriptor.java | 211 ++
.../com/sun/tools/attach/spi/AttachProvider.java | 240 ++
.../modules/agent/AbstractClassTransformer.java | 68 +
.../modules/agent/AgentInitialization.java | 101 +
.../org/powermock/modules/agent/AgentLoader.java | 152 +
.../agent/DefinalizingClassTransformer.java | 41 +
.../powermock/modules/agent/PowerMockAgent.java | 108 +
.../modules/agent/PowerMockClassRedefiner.java | 47 +
.../modules/agent/PowerMockClassTransformer.java | 94 +
.../modules/agent/PowerMockClassVisitor.java | 35 +
.../agent/support/JavaAgentClassRegisterImpl.java | 60 +
.../support/PowerMockAgentTestInitializer.java | 91 +
.../powermock/objectweb/asm/AnnotationVisitor.java | 169 ++
.../powermock/objectweb/asm/AnnotationWriter.java | 371 +++
.../org/powermock/objectweb/asm/Attribute.java | 255 ++
.../org/powermock/objectweb/asm/ByteVector.java | 339 +++
.../org/powermock/objectweb/asm/ClassReader.java | 2506 +++++++++++++++++
.../org/powermock/objectweb/asm/ClassVisitor.java | 320 +++
.../org/powermock/objectweb/asm/ClassWriter.java | 1776 ++++++++++++
.../java/org/powermock/objectweb/asm/Context.java | 145 +
.../java/org/powermock/objectweb/asm/Edge.java | 75 +
.../org/powermock/objectweb/asm/FieldVisitor.java | 150 +
.../org/powermock/objectweb/asm/FieldWriter.java | 329 +++
.../java/org/powermock/objectweb/asm/Frame.java | 1462 ++++++++++
.../java/org/powermock/objectweb/asm/Handle.java | 170 ++
.../java/org/powermock/objectweb/asm/Handler.java | 121 +
.../java/org/powermock/objectweb/asm/Item.java | 313 +++
.../java/org/powermock/objectweb/asm/LICENSE.txt | 28 +
.../java/org/powermock/objectweb/asm/Label.java | 565 ++++
.../org/powermock/objectweb/asm/MethodVisitor.java | 881 ++++++
.../org/powermock/objectweb/asm/MethodWriter.java | 2915 ++++++++++++++++++++
.../java/org/powermock/objectweb/asm/Opcodes.java | 361 +++
.../java/org/powermock/objectweb/asm/Type.java | 896 ++++++
.../java/org/powermock/objectweb/asm/TypePath.java | 196 ++
.../org/powermock/objectweb/asm/TypeReference.java | 452 +++
.../org/powermock/objectweb/asm/package-info.java | 34 +
.../java/sun/tools/attach/BsdVirtualMachine.java | 308 +++
.../sun/tools/attach/HotSpotVirtualMachine.java | 294 ++
.../java/sun/tools/attach/LinuxVirtualMachine.java | 344 +++
.../sun/tools/attach/SolarisVirtualMachine.java | 252 ++
.../sun/tools/attach/WindowsVirtualMachine.java | 194 ++
.../org,powermock/modules/agent/package.html | 33 +
modules/module-impl/junit3/pom.xml | 32 +
.../powermock/modules/junit3/PowerMockSuite.java | 123 +
.../junit3/internal/JUnit3TestSuiteChunker.java | 53 +
.../internal/PowerMockJUnit3RunnerDelegate.java | 41 +
.../internal/impl/JUnit3TestSuiteChunkerImpl.java | 241 ++
.../impl/PowerMockJUnit3RunnerDelegateImpl.java | 142 +
.../internal/impl/PowerMockJUnit3TestListener.java | 74 +
modules/module-impl/junit4-common/pom.xml | 35 +
.../common/internal/JUnit4TestSuiteChunker.java | 30 +
.../internal/PowerMockJUnitRunnerDelegate.java | 30 +
.../impl/AbstractCommonPowerMockRunner.java | 74 +
.../internal/impl/JUnit4TestMethodChecker.java | 50 +
.../internal/impl/JUnit4TestSuiteChunkerImpl.java | 238 ++
.../junit4/common/internal/impl/JUnitVersion.java | 30 +
.../internal/impl/PowerMockJUnit4RunListener.java | 91 +
.../common/internal/impl/VersionComparator.java | 98 +
.../common/internal/impl/VersionTokenizer.java | 74 +
.../common/internal/impl/JUnitVersionTest.java | 39 +
modules/module-impl/junit4-legacy/pom.xml | 43 +
.../modules/junit4/legacy/PowerMockRunner.java | 26 +
.../internal/impl/PowerMockJUnit4LegacyFilter.java | 74 +
.../PowerMockJUnit4LegacyRunnerDelegateImpl.java | 99 +
...owerMockJUnit4LegacyTestClassMethodsRunner.java | 100 +
.../PowerMockJUnit4LegacyTestIntrospector.java | 38 +
.../PowerMockJUnit4LegacyTestMethodRunner.java | 132 +
modules/module-impl/junit4-rule-agent/pom.xml | 36 +
.../modules/junit4/rule/PowerMockRule.java | 135 +
modules/module-impl/junit4-rule/pom.xml | 59 +
.../junit4/rule/PowerMockClassloaderExecutor.java | 55 +
.../modules/junit4/rule/PowerMockRule.java | 93 +
.../junit4/rule/PowerMockRuleTestSuiteChunker.java | 39 +
modules/module-impl/junit4/pom.xml | 41 +
.../powermock/modules/junit4/PowerMockRunner.java | 64 +
.../modules/junit4/PowerMockRunnerDelegate.java | 102 +
.../internal/impl/DelegatingPowerMockRunner.java | 182 ++
.../junit4/internal/impl/NotificationBuilder.java | 313 +++
.../impl/PowerMockJUnit44RunnerDelegateImpl.java | 383 +++
.../impl/PowerMockJUnit47RunnerDelegateImpl.java | 155 ++
.../impl/PowerMockJUnit49RunnerDelegateImpl.java | 75 +
.../junit4/internal/impl/PowerMockRunNotifier.java | 160 ++
.../PowerMockJUnit4MethodValidator.java | 133 +
.../internal/impl/PowerMockRunNotifierTest.java | 93 +
modules/module-impl/pom.xml | 31 +
modules/module-impl/testng-agent/pom.xml | 36 +
.../modules/testng/PowerMockObjectFactory.java | 52 +
modules/module-impl/testng-common/pom.xml | 35 +
.../modules/testng/PowerMockTestCase.java | 177 ++
modules/module-impl/testng/pom.xml | 31 +
.../modules/testng/PowerMockObjectFactory.java | 69 +
.../powermock/modules/testng/internal/Assumes.java | 34 +
.../testng/internal/ClassLoaderFactory.java | 75 +
.../internal/ExpectedExceptionsExtractor.java | 27 +
.../PowerMockClassloaderObjectFactory.java | 55 +
.../PowerMockExpectedExceptionsExtractorImpl.java | 52 +
.../internal/PowerMockTestNGMethodHandler.java | 80 +
.../testng/internal/TestClassInstanceFactory.java | 105 +
.../testng/internal/TestNGMethodFilter.java | 60 +
modules/module-test/easymock/junit3-test/pom.xml | 50 +
.../test/java/samples/junit3/AllJUnit3Tests.java | 33 +
.../AnnotationDemoWithSetupMethodTest.java | 40 +
.../PrivateFinalWithAnnotationTest.java | 55 +
.../junit3/privateandfinal/PrivateFinalTest.java | 69 +
.../privateandfinal/StupidPrivateFinalTest.java | 70 +
.../samples/junit3/singleton/MockStaticTest.java | 177 ++
.../SuppressConstructorHierarchyDemoTest.java | 68 +
modules/module-test/easymock/junit4-agent/pom.xml | 46 +
.../junit4/agent/AnnotationUsageTest.java | 80 +
.../powermockito/junit4/agent/LargeMethodTest.java | 58 +
.../easymock/junit4-legacy-test/pom.xml | 31 +
.../junit4/legacy/AllJUnit4LegacyTests.java | 28 +
.../AnnotationDemoWithSetupMethodTest.java | 43 +
.../FinalDemoWithAnnotationInjectionTest.java | 81 +
.../legacy/noannotation/NoAnnotationUsageTest.java | 78 +
.../SetUpAndTearDownWhenExtendingTestCaseTest.java | 30 +
...tUpAndTearDownWhenNotExtendingTestCaseTest.java | 27 +
.../junit4/legacy/singleton/MockStaticTest.java | 187 ++
.../SuppressConstructorHierarchyDemoTest.java | 69 +
modules/module-test/easymock/junit4-test/pom.xml | 36 +
.../InterfaceMethodHierarchyUsageTest.java | 64 +
.../test/java/samples/junit4/AllJUnit4Tests.java | 51 +
.../test/java/samples/junit4/SomeJUnit4Tests.java | 52 +
.../abstractmocking/AbstractMethodMockingTest.java | 30 +
.../AnnotationDemoWithSetupMethodTest.java | 42 +
...thAnnotationInjectionAndFieldDefaulterTest.java | 90 +
.../FinalDemoWithAnnotationInjectionTest.java | 81 +
.../FinalDemoWithNiceAnnotationInjectionTest.java | 54 +
...FinalDemoWithStrictAnnotationInjectionTest.java | 69 +
.../TestSubjectEasymockAnnotationTest.java | 44 +
.../TestSubjectPowermockAnnotationTest.java | 80 +
.../java/samples/junit4/assume/AssumeTest.java | 18 +
.../junit4/classhierarchy/CommonParentTest.java | 46 +
.../ClassWithInnerMembersTest.java | 119 +
.../java/samples/junit4/console/ConsoleTest.java | 39 +
.../PrivateConstructorInstantiationDemoTest.java | 46 +
.../PublicConstructorWithDependencyDemoTest.java | 76 +
.../constructorargs/ConstructorArgsDemoTest.java | 78 +
.../easymock/EasyMockAndPowerMockMixTest.java | 38 +
.../junit4/enummocking/EnumMockingTest.java | 32 +
.../equalswithgetclass/EqualsWithGetClassTest.java | 57 +
.../junit4/expectnew/ExpectNewDemoTest.java | 657 +++++
.../expectnew/ExpectNewOfFinalSystemClassTest.java | 28 +
.../samples/junit4/expectnew/MockDateTest.java | 83 +
.../expectnew/PrimitiveAndWrapperDemoTest.java | 42 +
.../expectnew/PrimitiveAndWrapperUserTest.java | 62 +
.../junit4/expectvoid/ExpectVoidDemoTest.java | 84 +
.../samples/junit4/finalmocking/FinalDemoTest.java | 79 +
...ingOfInstanceMethodsInFinalSystemClassTest.java | 83 +
.../junit4/finalmocking/NoDuplicateTest.java | 63 +
.../PowerMockUsesIdentityHashMapToStoreMocks.java | 32 +
...eValueOfStaticFinalFieldInInterfacesDefect.java | 42 +
.../junit4/java/MockClassesInsideJavaPackage.java | 43 +
.../junit4/largemethod/LargeMethodTest.java | 73 +
.../PrivateInnerInterfacesInTestClassTest.java | 27 +
.../mockpolicy/MockPolicyUsageExampleTest.java | 58 +
.../mockpolicy/MockPolicyWithExpectationsTest.java | 67 +
.../MockPolicyWithInvocationHandlerTest.java | 69 +
.../SimpleFrameworkMockPolicy.java | 42 +
.../frameworkexample/SimpleFrameworkUserTest.java | 36 +
.../multireplayverify/MultiReplayVerifyTest.java | 60 +
.../nativemocking/NativeMockingSampleTest.java | 47 +
.../samples/junit4/newmocking/StupidNewTest.java | 85 +
.../java/samples/junit4/nice/NiceDemoTest.java | 29 +
.../junit4/noannotation/NoAnnotationUsageTest.java | 77 +
.../SetUpAndTearDownWhenExtendingTestCaseTest.java | 30 +
...tUpAndTearDownWhenNotExtendingTestCaseTest.java | 27 +
...pIsOnlyCalledOnceWhenExtendingTestCaseTest.java | 19 +
...tringConstructorWorksWhenExtendingTestCase.java | 62 +
...WithSameNameButDifferentDefinitionTypeTest.java | 68 +
.../junit4/overloading/OverloadingDemoTest.java | 97 +
.../junit4/partialmocking/MockSelfDemoTest.java | 202 ++
.../MockSelfDemoWithSubClassTest.java | 54 +
.../PartialMockingWithConstructorTest.java | 51 +
...ialMockingWithConstructorUsingEasyMockTest.java | 60 +
.../PowerMockIgnoreAndPrepareForTest.java | 30 +
.../junit4/powermockignore/SomeJUnit4Tests.java | 52 +
...emoUsingThePrepareEverythingAnnotationTest.java | 657 +++++
.../junit4/privateandfinal/PrivateFinalTest.java | 73 +
.../MockSelfPrivateFieldServiceClassTest.java | 64 +
.../SimplePrivateFieldServiceClassTest.java | 71 +
.../privatemocking/PrivateMethodDemoTest.java | 214 ++
.../reflection/ReflectionInstantiatorTest.java | 49 +
.../replayall/ReplayAllForExpectNewTest.java | 118 +
.../replayall/ReplayAllForStaticMethodsTest.java | 55 +
.../resetmock/ResetForStaticMethodsTest.java | 52 +
.../samples/junit4/resetmock/ResetMockTest.java | 122 +
.../junit4/servletmocking/SampleServletTest.java | 51 +
.../simplereturn/SimpleReturnExampleUserTest.java | 30 +
.../singleton/LogicAndTestInSameClassTest.java | 50 +
.../singleton/MockStaticNotPreparedTest.java | 31 +
.../samples/junit4/singleton/MockStaticTest.java | 201 ++
.../junit4/singleton/SimpleStaticServiceTest.java | 41 +
.../samples/junit4/stackoverflow/EvilHashCode.java | 35 +
.../junit4/stackoverflow/StackOverFlowTest.java | 35 +
.../StaticAndInstanceDemoTest.java | 92 +
...aticAndInstanceWithConstructorCodeDemoTest.java | 65 +
.../AbstractStaticInitializerTest.java | 40 +
.../EvilStaticInitializerExampleTest.java | 49 +
.../InterfaceStaticInitializerExampleTest.java | 40 +
.../StaticInitializerExampleTest.java | 41 +
.../java/samples/junit4/strict/StrictDemoTest.java | 58 +
.../samples/junit4/stubmethod/StubMethodTest.java | 131 +
.../suppressconstructor/CreateUnmockedTest.java | 64 +
.../SuppressConstructorDemoTest.java | 89 +
.../SuppressConstructorHierarchyDemoTest.java | 74 +
.../SuppressNonParentConstructorDemoTest.java | 38 +
.../junit4/suppressfield/ItemRepositoryTest.java | 26 +
.../junit4/suppressfield/SuppressFieldTest.java | 98 +
.../junit4/suppressmethod/SuppressMethodTest.java | 186 ++
.../junit4/swing/ReallySimpleSwingDemoTest.java | 39 +
.../samples/junit4/system/FieldMockDefect.java | 44 +
.../samples/junit4/system/SystemClassUserTest.java | 229 ++
.../junit4/testhierarchy/RunWithHierarchyTest.java | 30 +
.../samples/junit4/testhierarchy/TestParent.java | 24 +
.../junit4/verify/AssertVerifyWorksTest.java | 40 +
.../PowerMockConstructorFiltrationTest.java | 33 +
.../methodhierarchy/MethodInvocationDemoTest.java | 119 +
.../packageprivate/PackagePrivateClassTest.java | 49 +
.../SuppressDefaultConstructorTest.java | 61 +
.../SuppressSpecificConstructorDemoTest.java | 45 +
modules/module-test/easymock/junit410-test/pom.xml | 31 +
.../junit410/assume/AssumeForJUnit410Test.java | 17 +
.../junit410/expectnew/ExpectNewDemoTest.java | 658 +++++
.../expectnew/ExpectNewOfFinalSystemClassTest.java | 43 +
.../rules/AssertThatJUnit410RulesWorks.java | 67 +
.../junit410/rules/ExceptionHandlingRuleTest.java | 66 +
.../junit410/rules/NoRuleAssertionErrorTest.java | 31 +
.../rules/impl/SimpleEasyMockJUnitRule.java | 69 +
modules/module-test/easymock/junit45-test/pom.xml | 31 +
.../modules/test/junit45/failure/MyClass.java | 27 +
.../modules/test/junit45/failure/MyException.java | 21 +
.../modules/test/junit45/failure/MyUtils.java | 24 +
.../failure/AssertThatJUnit45FailuresWorkTest.java | 64 +
modules/module-test/easymock/junit47-test/pom.xml | 31 +
...thAnnotationInjectionAndFieldDefaulterTest.java | 89 +
.../junit4/expectnew/ExpectNewDemoTest.java | 657 +++++
.../expectnew/ExpectNewOfFinalSystemClassTest.java | 43 +
.../junit4/rules/AssertThatJUnit47RulesWorks.java | 68 +
.../junit4/rules/NoRuleAssertionErrorTest.java | 31 +
.../java/samples/junit4/rules/RuleOrderTest.java | 48 +
.../samples/junit4/rules/ThrowingRuleTest.java | 52 +
modules/module-test/easymock/junit48-test/pom.xml | 31 +
.../junit48/expectnew/ExpectNewDemoTest.java | 657 +++++
.../expectnew/ExpectNewOfFinalSystemClassTest.java | 43 +
.../junit48/rules/AssertThatJUnit48RulesWorks.java | 68 +
.../junit48/rules/ExceptionHandlingRuleTest.java | 66 +
.../junit48/rules/NoRuleAssertionErrorTest.java | 31 +
.../java/samples/junit48/rules/RuleOrderTest.java | 48 +
.../samples/junit48/rules/ThrowingRuleTest.java | 52 +
.../rules/impl/SimpleEasyMockJUnitRule.java | 69 +
modules/module-test/easymock/pom.xml | 48 +
.../module-test/easymock/testng-agent-test/pom.xml | 45 +
.../samples/testng/agent/AnnotationDemoTest.java | 36 +
.../agent/AnnotationDemoWithBeforeMethodTest.java | 44 +
.../java/samples/testng/agent/FinalDemoTest.java | 78 +
.../MockStaticExtendsPowerMockTestCaseTest.java | 79 +
.../java/samples/testng/agent/MockStaticTest.java | 66 +
.../agent/NotAnnotatedWithPrepareForTest.java | 31 +
.../agent/PartialMockingWithBeforeClassTest.java | 53 +
.../samples/testng/agent/PrivateFinalTest.java | 67 +
.../samples/testng/agent/SampleServletTest.java | 56 +
.../samples/testng/agent/SystemClassUserTest.java | 215 ++
.../easymock/testng-agent-test/suite.xml | 17 +
modules/module-test/easymock/testng-test/pom.xml | 50 +
.../java/samples/testng/AnnotationDemoTest.java | 35 +
.../testng/AnnotationDemoWithBeforeMethodTest.java | 43 +
.../samples/testng/DocumentBuilderFactoryTest.java | 13 +
.../src/test/java/samples/testng/FinalTest.java | 29 +
.../MockStaticExtendsPowerMockTestCaseTest.java | 79 +
.../test/java/samples/testng/MockStaticTest.java | 66 +
.../testng/NotAnnotatedWithPrepareForTest.java | 31 +
.../testng/PartialMockingWithBeforeClassTest.java | 53 +
.../test/java/samples/testng/PrivateFinalTest.java | 67 +
.../java/samples/testng/SampleServletTest.java | 56 +
.../testng/StaticInitializerExampleTest.java | 43 +
.../java/samples/testng/SystemClassUserTest.java | 214 ++
modules/module-test/easymock/testng-test/suite.xml | 18 +
modules/module-test/junit4/pom.xml | 30 +
.../proxyframework/ProxyFrameworkImpl.java | 18 +
.../MockingFrameworkReporterFactoryImpl.java | 21 +
.../junit4/bugs/github352/GitHub352Test.java | 49 +
.../junit4/bugs/github352/MyAbstractTest.java | 17 +
.../powermockito/junit4/bugs/github352/MyTest.java | 27 +
.../junit4/bugs/github352/package-info.java | 4 +
modules/module-test/mockito/junit4-agent/pom.xml | 45 +
.../junit4/agent/AnnotationUsageTest.java | 77 +
...sertPowerMockRuleDelagatesToOtherRulesTest.java | 90 +
.../powermockito/junit4/agent/FinalDemoTest.java | 141 +
.../powermockito/junit4/agent/LargeMethodTest.java | 58 +
.../agent/MemberModificationExampleTest.java | 193 ++
.../agent/MockFinalUsingAnnotationsTest.java | 76 +
.../powermockito/junit4/agent/MockStaticTest.java | 181 ++
.../agent/MockStaticWithPrivateCtorTest.java | 43 +
.../junit4/agent/PrivateInstanceMockingTest.java | 116 +
.../powermockito/junit4/agent/StubMethodTest.java | 133 +
.../junit4/agent/SuppressConstructorDemoTest.java | 67 +
.../SuppressConstructorHierarchyDemoTest.java | 80 +
.../junit4/agent/SystemClassUserTest.java | 133 +
.../powermockito/junit4/agent/WhenNewTest.java | 600 ++++
.../junit4/agent/github512/Github512Test.java | 26 +
.../junit4/agent/github512/package-info.java | 4 +
.../module-test/mockito/junit4-delegate/pom.xml | 29 +
.../test/mockito/junit4/delegate/EnclosedTest.java | 87 +
.../junit4/delegate/MultipleConstructorsTest.java | 38 +
.../test/mockito/junit4/delegate/SelfieTest.java | 93 +
.../junit4/delegate/SubclassDelegateTest.java | 36 +
.../test/mockito/junit4/delegate/SuperClass.java | 18 +
.../mockito/junit4/delegate/SuppressedMethod.java | 42 +
.../junit4/delegate/SuppressedMethodStubbing.java | 74 +
.../junit4/delegate/SystemClassUserCases.java | 124 +
.../junit4/delegate/SystemClassUserMethod.java | 51 +
.../mockito/junit4/delegate/WhenNewCaseMethod.java | 61 +
.../test/mockito/junit4/delegate/WhenNewCases.java | 588 ++++
.../delegate/parameterized/FinalDemoTest.java | 145 +
.../MockFinalUsingAnnotationsTest.java | 89 +
.../delegate/parameterized/StubMethodTest.java | 77 +
.../parameterized/SuppressConstructorDemoTest.java | 76 +
.../SuppressConstructorHierarchyDemoTest.java | 108 +
.../parameterized/SupressMethodExampleTest.java | 177 ++
.../parameterized/SystemClassUserTest.java | 77 +
.../junit4/delegate/parameterized/WhenNewTest.java | 63 +
.../module-test/mockito/junit4-java8-agent/pom.xml | 48 +
.../junit4/bugs/github510/ClassUsesInterface.java | 12 +
.../junit4/bugs/github510/InterfaceWithStatic.java | 12 +
.../bugs/github510/ClassUsesInterfaceTest.java | 42 +
.../mockito/junit4-java8-rule-xstream/pom.xml | 48 +
.../junit4/bugs/github510/ClassUsesInterface.java | 12 +
.../junit4/bugs/github510/InterfaceWithStatic.java | 12 +
.../bugs/github510/ClassUsesInterfaceTest.java | 42 +
modules/module-test/mockito/junit4-java8/pom.xml | 38 +
.../junit4/bugs/github510/ClassUsesInterface.java | 16 +
.../junit4/bugs/github510/ConstructorObject.java | 10 +
.../junit4/bugs/github510/InterfaceWithStatic.java | 16 +
.../InterfaceMethodExceedingJvmLimit.java | 49 +
.../largemethod/LargeMethodInInterfaceTest.java | 56 +
.../junit4/bugs/github510/Github510Test.java | 51 +
.../junit4/bugs/github510/package-info.java | 4 +
.../mockito/junit4-rule-objenesis/pom.xml | 33 +
.../junit4/rule/objenesis/FinalDemoTest.java | 141 +
.../powermockito/junit4/rule/objenesis/Foo.java | 23 +
.../junit4/rule/objenesis/MockStaticTest.java | 180 ++
.../junit4/rule/objenesis/PowerMockRuleTest.java | 52 +
.../rule/objenesis/PrivateInstanceMockingTest.java | 117 +
.../objenesis/StaticInitializerExampleTest.java | 28 +
.../junit4/rule/objenesis/SystemClassUserTest.java | 134 +
.../junit4/rule/objenesis/WhenNewTest.java | 602 ++++
.../objenesis/bugs/github512/Github512Test.java | 24 +
.../objenesis/bugs/github512/package-info.java | 4 +
.../mockito/junit4-rule-xstream/pom.xml | 33 +
...sertPowerMockRuleDelagatesToOtherRulesTest.java | 89 +
.../junit4/rule/xstream/FinalDemoTest.java | 141 +
.../powermockito/junit4/rule/xstream/Foo.java | 23 +
.../junit4/rule/xstream/MockStaticTest.java | 180 ++
.../junit4/rule/xstream/PowerMockRuleTest.java | 52 +
.../rule/xstream/PrivateInstanceMockingTest.java | 116 +
.../rule/xstream/StaticInitializerExampleTest.java | 28 +
.../junit4/rule/xstream/SystemClassUserTest.java | 134 +
.../junit4/rule/xstream/WhenNewTest.java | 601 ++++
.../rule/xstream/github512/Github512Test.java | 24 +
.../rule/xstream/github512/package-info.java | 4 +
modules/module-test/mockito/junit4/pom.xml | 25 +
.../powermockito/junit4/ClassLoaderBugTest.java | 54 +
.../powermockito/junit4/FinalEqualsClass.java | 33 +
.../powermockito/junit4/FinalEqualsClassTest.java | 50 +
.../abstractmocking/AbstractMethodMockingTest.java | 51 +
.../annotationbased/CaptorAnnotationTest.java | 72 +
.../ChunkingAndStaticInitializerRemovalTest.java | 61 +
.../annotationbased/InjectMocksAnnotationTest.java | 75 +
.../MockFinalUsingAnnotationsTest.java | 73 +
.../MockFinalUsingAnnotationsWithAnswersTest.java | 58 +
.../junit4/annotationbased/SpyAnnotationTest.java | 52 +
.../argumentmatcher/ArgumentMatcherTest.java | 46 +
.../junit4/bugs/github510/package-info.java | 4 +
.../junit4/bugs/github583/ChildClass.java | 20 +
.../bugs/github583/ClassWithInheritanceTest.java | 22 +
.../junit4/bugs/github583/ParenClass.java | 14 +
.../junit4/bugs/github583/package-info.java | 4 +
.../constructor/InnerConstructorsAreFoundTest.java | 122 +
.../powermockito/junit4/doreturn/DoReturnTest.java | 52 +
.../junit4/enums/EnumWithConstructorTest.java | 36 +
.../junit4/equalsmocking/EqualsMockingTest.java | 52 +
.../junit4/finalmocking/FinalDemoTest.java | 135 +
.../powermockito/junit4/getclass/GetClassTest.java | 58 +
.../powermockito/junit4/hashcode/HashCodeTest.java | 51 +
.../junit4/hashcode/InnerClassHashCodeTest.java | 73 +
.../junit4/largemethod/LargeMethodTest.java | 56 +
.../MemberModificationExampleTest.java | 187 ++
.../NestedClassDefinedInsideTestCaseTest.java | 60 +
.../partialmocking/PartialMockingExampleTest.java | 47 +
.../PartialMockingRetainsStateTest.java | 47 +
.../PrivatePartialMockingExampleTest.java | 89 +
.../partialmocking/StaticPartialMockingTest.java | 233 ++
.../privatemocking/PrivateInstanceMockingTest.java | 166 ++
.../junit4/proxymethod/ProxyMethodTest.java | 128 +
.../junit4/simplemix/SimpleMixTest.java | 79 +
.../samples/powermockito/junit4/spy/SpyTest.java | 77 +
.../StaticAndInstanceDemoTest.java | 47 +
.../staticmocking/MockStaticNotPreparedTest.java | 58 +
.../junit4/staticmocking/MockStaticTest.java | 228 ++
.../junit4/stress/PowerMockStressTest.java | 91 +
.../junit4/system/ServiceLoaderTest.java | 41 +
.../junit4/system/SystemClassUserTest.java | 215 ++
.../powermockito/junit4/tostring/ToStringTest.java | 44 +
.../VerifyNoMoreInteractionsTest.java | 133 +
...tSupportCreatingMocksInFieldsWhenNewDefect.java | 51 +
.../junit4/whennew/NewFileExampleTest.java | 46 +
.../junit4/whennew/VerifyNewMultipleTimesTest.java | 63 +
.../whennew/VerifyNewWithoutWhenNewTest.java | 52 +
.../powermockito/junit4/whennew/WhenNewTest.java | 635 +++++
.../junit4/withsettings/WithSettingsTest.java | 59 +
modules/module-test/mockito/junit49/pom.xml | 30 +
.../powermockito/junit4/rules/JUnit49RuleTest.java | 78 +
modules/module-test/mockito/pom.xml | 92 +
modules/module-test/mockito/testng/pom.xml | 82 +
.../staticmocking/MockStaticNotPreparedTest.java | 31 +
.../MockStaticPreparedWithoutMockStaticTest.java | 24 +
.../staticmocking/Mockito1MockStaticTest.java | 74 +
.../staticmocking/Mockito2MockStaticTest.java | 79 +
modules/module-test/mockito/testng/suite.xml | 39 +
modules/module-test/pom.xml | 32 +
modules/module-test/testng/pom.xml | 49 +
.../proxyframework/ProxyFrameworkImpl.java | 18 +
.../test/java/samples/testng/SimpleBaseTest.java | 120 +
.../samples/testng/bugs/github647/GitHub647.java | 93 +
.../testng/bugs/github647/SkipExceptionTest.java | 17 +
.../samples/testng/bugs/github647/SomeClass.java | 12 +
modules/module-test/testng/suite.xml | 8 +
modules/pom.xml | 23 +
pom.xml | 392 +++
powermock.png | Bin 0 -> 11350 bytes
reflect/pom.xml | 27 +
.../main/java/org/powermock/reflect/Whitebox.java | 857 ++++++
.../exceptions/ConstructorNotFoundException.java | 57 +
.../reflect/exceptions/FieldNotFoundException.java | 38 +
.../exceptions/MethodInvocationException.java | 75 +
.../exceptions/MethodNotFoundException.java | 38 +
.../TooManyConstructorsFoundException.java | 39 +
.../exceptions/TooManyFieldsFoundException.java | 38 +
.../exceptions/TooManyMethodsFoundException.java | 38 +
.../internal/CandidateConstructorSearcher.java | 93 +
.../reflect/internal/ParameterTypesMatcher.java | 80 +
.../org/powermock/reflect/internal/TypeUtils.java | 95 +
.../powermock/reflect/internal/WhiteboxImpl.java | 2582 +++++++++++++++++
.../internal/comparator/ComparatorFactory.java | 107 +
.../AllFieldsMatcherStrategy.java | 33 +
.../AssignableFromFieldTypeMatcherStrategy.java | 49 +
.../AssignableToFieldTypeMatcherStrategy.java | 30 +
.../FieldAnnotationMatcherStrategy.java | 65 +
.../matcherstrategies/FieldMatcherStrategy.java | 49 +
.../FieldNameMatcherStrategy.java | 48 +
.../FieldTypeMatcherStrategy.java | 48 +
.../internal/primitivesupport/BoxedWrapper.java | 70 +
.../primitivesupport/PrimitiveWrapper.java | 97 +
.../reflect/matching/FieldMatchingStrategy.java | 36 +
.../ClassLoaderRegisterProxyFramework.java | 31 +
.../proxyframework/ProxyFrameworkHelper.java | 53 +
.../proxyframework/RegisterProxyFramework.java | 20 +
.../org/powermock/reflect/spi/ProxyFramework.java | 23 +
.../powermock/reflect/WhiteBoxGetFieldTest.java | 63 +
.../java/org/powermock/reflect/WhiteBoxTest.java | 947 +++++++
.../context/ClassFieldsNotInTargetContext.java | 38 +
.../context/InstanceFieldsNotInTargetContext.java | 38 +
.../org/powermock/reflect/context/MyContext.java | 37 +
.../powermock/reflect/context/MyIntContext.java | 27 +
.../powermock/reflect/context/MyStringContext.java | 25 +
...InstanceAndOneStaticFieldOfSameTypeContext.java | 32 +
.../reflect/internal/WhiteboxImplTest.java | 88 +
.../reflect/testclasses/AbstractClass.java | 20 +
.../powermock/reflect/testclasses/AnInterface.java | 20 +
.../org/powermock/reflect/testclasses/Child.java | 20 +
.../reflect/testclasses/ClassWithAMethod.java | 27 +
.../ClassWithChildThatHasInternalState.java | 23 +
.../ClassWithInterfaceConstructors.java | 31 +
.../testclasses/ClassWithInternalState.java | 85 +
.../reflect/testclasses/ClassWithList.java | 26 +
.../ClassWithMethodUsingSuperTypeArgument.java | 22 +
.../testclasses/ClassWithObjectConstructors.java | 19 +
.../ClassWithOverloadedConstructors.java | 39 +
.../testclasses/ClassWithOverloadedMethods.java | 27 +
.../testclasses/ClassWithOverriddenMethod.java | 24 +
.../ClassWithPrimitiveConstructors.java | 18 +
.../testclasses/ClassWithPrivateMethods.java | 69 +
.../testclasses/ClassWithSerializableState.java | 34 +
.../ClassWithSeveralMethodsWithSameName.java | 27 +
...ralMethodsWithSameNameOneWithoutParameters.java | 31 +
.../testclasses/ClassWithSimpleInternalState.java | 46 +
.../ClassWithSimpleStateOfSameType.java | 31 +
.../testclasses/ClassWithStandardMethod.java | 24 +
...thStaticAndInstanceInternalStateOfSameType.java | 36 +
.../reflect/testclasses/ClassWithStaticMethod.java | 30 +
.../testclasses/ClassWithUniquePrivateMethods.java | 37 +
.../testclasses/ClassWithVarArgsConstructor.java | 32 +
.../testclasses/ClassWithVarArgsConstructor2.java | 32 +
.../org/powermock/reflect/testclasses/Parent.java | 20 +
release/easymock-extension-api-full/pom.xml | 162 ++
.../src/assembly/full.xml | 15 +
release/junit-without-mock-framework/pom.xml | 71 +
.../src/assembly/full.xml | 15 +
release/mockito-extension-api-full/pom.xml | 162 ++
.../src/assembly/full.xml | 15 +
release/mockito2-extension-api-full/pom.xml | 180 ++
.../src/assembly/full.xml | 33 +
release/pom.xml | 64 +
release/testng-without-mock-framework/pom.xml | 61 +
.../src/assembly/full.xml | 15 +
release/with-junit-easymock-dependencies/pom.xml | 66 +
.../src/assembly/final.xml | 12 +
release/with-junit-mockito-dependencies/pom.xml | 62 +
.../src/assembly/final.xml | 12 +
release/with-junit-mockito2-dependencies/pom.xml | 80 +
.../src/assembly/final.xml | 30 +
release/with-testng-easymock-dependencies/pom.xml | 65 +
.../src/assembly/final.xml | 12 +
release/with-testng-mockito-dependencies/pom.xml | 62 +
.../src/assembly/final.xml | 12 +
release/with-testng-mockito2-dependencies/pom.xml | 80 +
.../src/assembly/final.xml | 30 +
release/without-test-and-mock-framework/pom.xml | 65 +
.../src/assembly/full.xml | 15 +
src/site/apt/docs/gettingStarted.apt | 40 +
src/site/apt/docs/installing.apt | 24 +
src/site/apt/docs/motivation.apt | 130 +
src/site/resources/images/logos/jayway.png | Bin 0 -> 5895 bytes
src/site/resources/images/logos/powermock.png | Bin 0 -> 11350 bytes
src/site/site.xml | 60 +
tests/pom.xml | 22 +
tests/utils/pom.xml | 42 +
tests/utils/src/main/java/samples/Service.java | 27 +
.../abstractmocking/AbstractMethodMocking.java | 30 +
.../samples/annotationbased/AnnotationDemo.java | 35 +
.../samples/anonymousmocking/MyAbstractClass.java | 20 +
.../samples/anonymousmocking/StupidAnonymous.java | 87 +
.../argumentmatcher/ArgumentMatcherDemo.java | 26 +
.../main/java/samples/classhierarchy/ChildA.java | 20 +
.../main/java/samples/classhierarchy/ChildB.java | 20 +
.../main/java/samples/classhierarchy/Parent.java | 29 +
.../ClassWithInnerMembers.java | 115 +
.../constructor/PrivateConstructorDemo.java | 39 +
.../PrivateConstructorInstantiationDemo.java | 38 +
.../samples/constructor/PublicConstructorDemo.java | 39 +
.../PublicConstructorWithDependencyDemo.java | 39 +
.../constructorargs/ConstructorArgsDemo.java | 39 +
.../AnotherSomeObjectInterfaceImpl.java | 24 +
.../samples/enummocking/EnumWithConstructor.java | 36 +
.../src/main/java/samples/enummocking/MyEnum.java | 25 +
.../samples/enummocking/SomeObjectInterface.java | 24 +
.../enummocking/SomeObjectInterfaceImpl.java | 24 +
.../equalswithgetclass/EqualsWithGetClass.java | 54 +
.../main/java/samples/expectnew/ExpectNewDemo.java | 161 ++
.../expectnew/ExpectNewOfFinalSystemClassDemo.java | 24 +
.../samples/expectnew/ExpectNewServiceUser.java | 37 +
.../expectnew/ExpectNewWithMultipleCtorDemo.java | 41 +
.../java/samples/expectnew/NewFileExample.java | 34 +
.../samples/expectnew/PrimitiveAndWrapperDemo.java | 37 +
.../samples/expectnew/PrimitiveAndWrapperUser.java | 29 +
.../samples/expectnew/VarArgsConstructorDemo.java | 70 +
.../java/samples/expectvoid/ExpectVoidDemo.java | 28 +
.../samples/fieldmock/FieldInitializerDemo.java | 40 +
.../main/java/samples/finalmocking/FinalDemo.java | 44 +
.../samples/finalmocking/HoldingFinalDemo.java | 23 +
.../finalmocking/StaticHoldingFinalDemo.java | 23 +
.../hashcode/HashCodeInitializedInCtor.java | 37 +
.../java/samples/injectmocks/DependencyHolder.java | 34 +
.../injectmocks/DependencyHolderQualifier.java | 45 +
.../main/java/samples/injectmocks/InjectDemo.java | 36 +
.../injectmocks/InjectDependencyHolder.java | 34 +
.../InjectDependencyHolderQualifier.java | 43 +
.../ClassWithNonPrivateInnerClass.java | 36 +
.../ClassWithPrivateInnerClass.java | 37 +
.../InterfaceWithStaticFinalField.java | 27 +
.../InterfaceMethodHierarchyUsage.java | 53 +
.../samples/interfacemethodfinding/WsUtil.java | 32 +
.../java/samples/java/ClassInsideJavaPackage.java | 24 +
.../largemethod/MethodExceedingJvmLimit.java | 49 +
.../methodhierarchy/MethodInvocationDemo.java | 25 +
.../MethodInvocationDemoGrandParent.java | 33 +
.../MethodInvocationDemoParent.java | 29 +
.../java/samples/mockpolicy/ResultCalculator.java | 28 +
.../mockpolicy/SimpleClassWithADependency.java | 26 +
.../samples/mockpolicy/SomeClassWithAMethod.java | 24 +
.../mockpolicy/SomeClassWithAMethodParent.java | 23 +
.../mockpolicy/frameworkexample/NativeResult.java | 29 +
.../frameworkexample/SimpleFramework.java | 27 +
.../frameworkexample/SimpleFrameworkUser.java | 23 +
.../samples/nativemocking/NativeMockingSample.java | 32 +
.../java/samples/nativemocking/NativeService.java | 26 +
.../src/main/java/samples/newmocking/MyClass.java | 31 +
.../src/main/java/samples/newmocking/NewDemo.java | 26 +
.../java/samples/newmocking/SomeDependency.java | 27 +
.../main/java/samples/newmocking/StupidNew.java | 34 +
.../utils/src/main/java/samples/nice/NiceDemo.java | 32 +
.../overloading/OverloadedMethodsExample.java | 33 +
.../java/samples/overloading/OverloadingDemo.java | 43 +
.../StaticAndInstanceMethodWithSameName.java | 27 +
.../StaticAndInstanceMethodWithSameNameUser.java | 36 +
.../packageprivate/PackagePrivateClass.java | 33 +
.../java/samples/partialmocking/MockSelfDemo.java | 121 +
.../partialmocking/MockSelfDemoSubClass.java | 28 +
.../partialmocking/MockSelfDemoWithSubClass.java | 31 +
.../MockSelfWithNoDefaultConstructorDemo.java | 34 +
.../partialmocking/MockWithStaticStateDemo.java | 25 +
.../partialmocking/PartialMockingExample.java | 31 +
.../PartialMockingWithConstructor.java | 28 +
.../PrivatePartialMockingExample.java | 30 +
.../powermockignore/PowerMockIgnoreDemo.java | 10 +
.../java/samples/powermockito/MockitoVersion.java | 49 +
.../java/samples/privateandfinal/PrivateFinal.java | 32 +
.../privateandfinal/PrivateFinalOverload.java | 31 +
.../MockSelfPrivateFieldServiceClass.java | 37 +
.../SimplePrivateFieldServiceClass.java | 32 +
.../samples/privatemocking/PrivateMethodDemo.java | 103 +
.../samples/reflection/ReflectionInstantiator.java | 26 +
.../src/main/java/samples/reflection/UseMe.java | 21 +
.../java/samples/reflection/UseMeInterface.java | 22 +
.../src/main/java/samples/rule/SimpleThing.java | 21 +
.../main/java/samples/rule/SimpleThingCreator.java | 24 +
.../main/java/samples/rule/SimpleThingImpl.java | 26 +
.../src/main/java/samples/rule/ThingToTest.java | 31 +
.../java/samples/servletmocking/SampleServlet.java | 34 +
.../src/main/java/samples/simplemix/SimpleMix.java | 33 +
.../samples/simplemix/SimpleMixCollaborator.java | 25 +
.../samples/simplemix/SimpleMixConstruction.java | 23 +
.../java/samples/simplemix/SimpleMixUtilities.java | 24 +
.../samples/simplereturn/SimpleReturnExample.java | 8 +
.../simplereturn/SimpleReturnExampleUser.java | 15 +
.../samples/singleton/SimpleStaticService.java | 8 +
.../main/java/samples/singleton/StaticExample.java | 64 +
.../main/java/samples/singleton/StaticHelper.java | 27 +
.../main/java/samples/singleton/StaticService.java | 109 +
.../samples/singleton/StaticWithPrivateCtor.java | 28 +
.../utils/src/main/java/samples/spy/SpyObject.java | 32 +
.../staticandinstance/StaticAndInstanceDemo.java | 43 +
.../StaticAndInstanceWithConstructorCodeDemo.java | 36 +
.../AbstractStaticInitializerExample.java | 34 +
.../EvilStaticInitializerExample.java | 40 +
.../staticinitializer/InterfaceComputation.java | 51 +
.../SimpleStaticInitializerExample.java | 33 +
.../StaticInitializerExample.java | 35 +
.../main/java/samples/stress/ClassWithStatic.java | 45 +
.../src/main/java/samples/stress/StressSample.java | 44 +
.../src/main/java/samples/strict/StrictDemo.java | 32 +
.../samples/suppressconstructor/AppaleList.java | 41 +
.../suppressconstructor/InvokeConstructor.java | 23 +
.../SuppressConstructorDemo.java | 32 +
...uppressConstructorHeirarchyEvilGrandParent.java | 23 +
.../SuppressConstructorHierarchy.java | 34 +
.../SuppressConstructorHierarchyParent.java | 36 +
.../SuppressConstructorSubclassDemo.java | 29 +
.../SuppressNonParentConstructorDemo.java | 28 +
.../SuppressSpecificConstructorDemo.java | 33 +
.../suppresseverything/SuppressEverything.java | 35 +
.../java/samples/suppressfield/DomainObject.java | 7 +
.../java/samples/suppressfield/ItemRepository.java | 30 +
.../java/samples/suppressfield/SuppressField.java | 61 +
.../samples/suppressmethod/SuppressMethod.java | 82 +
.../suppressmethod/SuppressMethodExample.java | 33 +
.../suppressmethod/SuppressMethodParent.java | 24 +
.../java/samples/swing/ReallySimpleSwingDemo.java | 10 +
.../main/java/samples/swing/SimpleSwingDemo.java | 56 +
.../main/java/samples/system/SystemClassUser.java | 95 +
.../ClassWithPowerMockGeneratedConstructor.java | 32 +
1404 files changed, 139140 insertions(+)
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000..8ffc47b
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,29 @@
+Hey there and thank you for using PowerMock
+
+Please read the following tips before filing an issue:
+
+Is this something you can debug and fix?
+-------------------------------------------------------
+
+Can you see anything in the logs? Can you debug why this happens? **Send a pull request**! Bug fixes and documentation fixes are very welcome.
+
+
+Is this question about PowerMock usage?
+---------------------------------------
+
+The better way to ask question:
+
+* The mailing-list : https://groups.google.com/forum/#!forum/powermock / powermock at googlegroups.com
+* [Stackoverflow](http://stackoverflow.com/questions/tagged/powermock) with the tag 'powermock'. (Make sure you **include a short code snippet to demonstrate the problem** and if you have an exception then make sure **include stack trace**.)
+
+None of the above, want to create a GitHub issue
+------------------------------------------------------------------
+
+In order to help us to clarify issue can you answer the following question:
+
+What steps will reproduce the problem?
+What is the expected output?
+What do you see instead?
+What version of the product are you using?
+On what operating system?
+Please provide any additional information below.
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..2ed3c7e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+target
+*.iws
+*.ipr
+*.iml
+.classpath
+.project
+.settings
+.springBeans
+repo
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..b8d2e01
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: java
+jdk:
+ - oraclejdk8
+script:
+ - mvn install -DskipTests=true
+ - mvn test
+ - mvn test -Pmockito2
+ - mvn install -DskipTests=true -Pacceptance -Pmockito
+ - mvn test -Pacceptance -Pmockito
+ - mvn test -Pacceptance -Pmockito2
+
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5dc245e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,69 @@
+![PowerMock](powermock.png)
+
+[![Build Status](https://travis-ci.org/jayway/powermock.svg)](https://travis-ci.org/jayway/powermock)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.powermock/powermock/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.powermock/powermock)
+[![Javadoc](https://javadoc-emblem.rhcloud.com/doc/org.powermock/powermock/badge.svg)](http://www.javadoc.io/doc/org.powermock/powermock)
+[![Dependency Status](https://www.versioneye.com/user/projects/570b66ddfcc96900102d09f6/badge.svg?style=flat)](https://www.versioneye.com/user/projects/570b66ddfcc96900102d09f6)
+
+Usage status: Mockito: [![Reference Status](https://www.versioneye.com/java/org.powermock:powermock-api-mockito/reference_badge.svg?style=flat)](https://www.versioneye.com/java/org.powermock:powermock-api-mockito/references) Easymock: [![Reference Status](https://www.versioneye.com/java/org.powermock:powermock-api-easymock/reference_badge.svg?style=flat)](https://www.versioneye.com/java/org.powermock:powermock-api-easymock/references) jUnit: [![Reference Status](https://www.versioneye.co [...]
+
+Writing unit tests can be hard and sometimes good design has to be sacrificed for the sole purpose of testability. Often testability corresponds to good design, but this is not always the case. For example final classes and methods cannot be used, private methods sometimes need to be protected or unnecessarily moved to a collaborator, static methods should be avoided completely and so on simply because of the limitations of existing frameworks.
+
+PowerMock is a framework that extends other mock libraries such as EasyMock with more powerful capabilities. PowerMock uses a custom classloader and bytecode manipulation to enable mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more. By using a custom classloader no changes need to be done to the IDE or continuous integration servers which simplifies adoption. Developers familiar with the supported mock frameworks w [...]
+
+When writing unit tests it is often useful to bypass encapsulation and therefore PowerMock includes several features that simplifies reflection specifically useful for testing. This allows easy access to internal state, but also simplifies partial and private mocking.
+
+Please note that PowerMock is mainly intended for people with expert knowledge in unit testing. Putting it in the hands of junior developers may cause more harm than good.
+
+## News
+* 2015-12-11: PowerMock 1.6.4 has been released with better support for [Jacoco](http://eclemma.org/jacoco/) and improvements to the [DelegatingPowerMockRunner](https://github.com/jayway/powermock/wiki/JUnit_Delegating_Runner) as well as some other minor fixes. See [change log](https://raw.githubusercontent.com/jayway/powermock/master/changelog.txt) for details.
+* 2015-10-02: PowerMock 1.6.3 has been released with support for EasyMock 3.4 as well as compatibility with ByteBuddy and various other fixes. See [change log](https://raw.githubusercontent.com/jayway/powermock/master/changelog.txt) for details.
+* 2015-07-25: PowerMock has moved to GitHub. From now on the old <a href="https://code.google.com/p/powermock/">Google Code page</a> should not be used anymore. All issues are reported here on GitHub and the documentation is migrated.
+
+[Older News](https://github.com/jayway/powermock/wiki/OldNews)
+
+## Documentation
+* [Getting Started](https://github.com/jayway/powermock/wiki/GettingStarted)
+* [Downloads](https://github.com/jayway/powermock/wiki/Downloads)
+* [Motivation](https://github.com/jayway/powermock/wiki/Motivation)
+* Javadoc
+ * [EasyMock API extension](http://www.javadoc.io/doc/org.powermock/powermock-api-easymock/1.6.4) ([PowerMock class](http://static.javadoc.io/org.powermock/powermock-api-easymock/1.6.4/org/powermock/api/easymock/PowerMock.html))
+ * [Mockito API extension](http://www.javadoc.io/doc/org.powermock/powermock-api-mockito/1.6.4) ([PowerMockito class](http://static.javadoc.io/org.powermock/powermock-api-mockito/1.6.4/org/powermock/api/mockito/PowerMockito.html))
+ * [PowerMock Reflect](http://www.javadoc.io/doc/org.powermock/powermock-reflect/1.6.4) ([Whitebox class](http://static.javadoc.io/org.powermock/powermock-reflect/1.6.4/org/powermock/reflect/Whitebox.html))
+* [EasyMock](https://github.com/jayway/powermock/wiki/EasyMock)
+ * [Mock Static](https://github.com/jayway/powermock/wiki/MockStatic)
+ * [Mock Final](https://github.com/jayway/powermock/wiki/MockFinal)
+ * [Mock Private](https://github.com/jayway/powermock/wiki/MockPrivate)
+ * [Mock New](https://github.com/jayway/powermock/wiki/MockConstructor)
+ * [Mock Partial](https://github.com/jayway/powermock/wiki/MockPartial)
+ * [Replay and verify all](https://github.com/jayway/powermock/wiki/ReplayAllAndVerifyAll)
+* Mockito
+ * [Mockito 1.8+](https://github.com/jayway/powermock/wiki/MockitoUsage)
+ * [Mockito 1.7](https://github.com/jayway/powermock/wiki/MockitoUsage_Legacy)
+* Common
+ * [Bypass Encapsulation](https://github.com/jayway/powermock/wiki/BypassEncapsulation)
+ * [Suppress Unwanted Behavior](https://github.com/jayway/powermock/wiki/SuppressUnwantedBehavior)
+ * [Test Listeners](https://github.com/jayway/powermock/wiki/TestListeners)
+ * [Mock Policies](https://github.com/jayway/powermock/wiki/MockPolicies)
+ * [Mock system classes](https://github.com/jayway/powermock/wiki/MockSystem)
+* [TestNG](https://github.com/jayway/powermock/wiki/TestNG_usage)
+* [Delegate to another JUnit Runner](https://github.com/jayway/powermock/wiki/JUnit_Delegating_Runner)
+* [Tutorial](https://github.com/jayway/powermock/wiki/PowerMock_tutorial)
+* Experimental
+ * [Bootstrap using a JUnit Rule](https://github.com/jayway/powermock/wiki/PowerMockRule)
+ * [Bootstrap using a Java Agent](https://github.com/jayway/powermock/wiki/PowerMockAgent)
+* [OSGi](https://github.com/jayway/powermock/wiki/osgi)
+* [Release Notes](https://github.com/jayway/powermock/wiki/ReleaseNotes)
+* [FAQ](https://github.com/jayway/powermock/wiki/FAQ)
+
+## Support and discussion
+Join the mailing-list [here](http://groups.google.com/group/powermock) for questions, feedback and support.
+
+## Links
+* [Change log](https://raw.githubusercontent.com/jayway/powermock/master/changelog.txt)
+* [PowerMock on Ohloh](http://www.ohloh.net/p/powermock/)
+* [Mailing list for questions and support](http://groups.google.com/group/powermock)
+
+## Sponsored by:
+[![JAYWAY](http://www.jayway.com/wp-content/uploads/2014/05/jayway_rgb_inverted.png)](http://www.jayway.com/)
+
diff --git a/api/easymock/pom.xml b/api/easymock/pom.xml
new file mode 100644
index 0000000..fc98b93
--- /dev/null
+++ b/api/easymock/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-api-easymock</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock API for EasyMock.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/EasyMockConfiguration.java b/api/easymock/src/main/java/org/powermock/api/easymock/EasyMockConfiguration.java
new file mode 100644
index 0000000..fde018a
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/EasyMockConfiguration.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.easymock;
+
+/**
+ * Configuration information about EasyMock framework and which feature is supported by version of EasyMock in runtime.
+ *
+ * @since 1.6.5
+ */
+public class EasyMockConfiguration {
+
+ private static final EasyMockConfiguration INSTANCE = new EasyMockConfiguration();
+ private boolean testSubjectSupported;
+ private boolean reallyEasyMock;
+ private boolean injectMocksSupported;
+
+ private EasyMockConfiguration() {
+ initTestSubjectSupported();
+ initReallyEasyMock();
+ initInjectMocksSupported();
+ }
+
+ public static EasyMockConfiguration getConfiguration() {
+ return INSTANCE;
+ }
+
+ private void initTestSubjectSupported() {
+ try {
+ Class.forName("org.easymock.TestSubject");
+ testSubjectSupported = true;
+ } catch (ClassNotFoundException e) {
+ testSubjectSupported = false;
+ }
+ }
+
+ private void initReallyEasyMock() {
+ try {
+ Class.forName("org.easymock.EasyMockSupport");
+ reallyEasyMock = true;
+ } catch (ClassNotFoundException e) {
+ reallyEasyMock = false;
+ }
+ }
+
+ private void initInjectMocksSupported() {
+ try {
+ Class<?> clazz = Class.forName("org.easymock.EasyMockSupport");
+ clazz.getDeclaredMethod("injectMocks", Object.class);
+ injectMocksSupported = true;
+ } catch (NoSuchMethodException e) {
+ injectMocksSupported = false;
+ } catch (ClassNotFoundException e) {
+ injectMocksSupported = false;
+ }
+ }
+
+ public boolean isInjectMocksSupported() {
+ return injectMocksSupported;
+ }
+
+ public boolean isReallyEasyMock() {
+ return reallyEasyMock;
+ }
+
+ public boolean isTestSubjectSupported() {
+ return testSubjectSupported;
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/PowerMock.java b/api/easymock/src/main/java/org/powermock/api/easymock/PowerMock.java
new file mode 100644
index 0000000..f5dc1a7
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/PowerMock.java
@@ -0,0 +1,2125 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock;
+
+import net.sf.cglib.proxy.Enhancer;
+import org.easymock.ConstructorArgs;
+import org.easymock.IExpectationSetters;
+import org.easymock.IMocksControl;
+import org.easymock.internal.LastControl;
+import org.easymock.internal.MockInvocationHandler;
+import org.easymock.internal.MocksControl;
+import org.powermock.api.easymock.internal.invocationcontrol.EasyMockMethodInvocationControl;
+import org.powermock.api.easymock.internal.invocationcontrol.NewInvocationControlAssertionError;
+import org.powermock.api.easymock.internal.invocationcontrol.NewInvocationControlImpl;
+import org.powermock.api.easymock.internal.mockstrategy.MockStrategy;
+import org.powermock.api.easymock.internal.mockstrategy.impl.DefaultMockStrategy;
+import org.powermock.api.easymock.internal.mockstrategy.impl.NiceMockStrategy;
+import org.powermock.api.easymock.internal.mockstrategy.impl.StrictMockStrategy;
+import org.powermock.api.support.SuppressCode;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.ClassReplicaCreator;
+import org.powermock.core.DefaultFieldValueGenerator;
+import org.powermock.core.MockGateway;
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+/**
+ * PowerMock extends EasyMock functionality with several new features such as
+ * mocking static and private methods, mocking new instances and more. Use
+ * PowerMock instead of EasyMock where applicable.
+ */
+public class PowerMock extends MemberModifier {
+
+ private static final String NICE_REPLAY_AND_VERIFY_KEY = "PowerMock.niceReplayAndVerify";
+
+ static {
+ MockGateway.MOCK_STANDARD_METHODS = false;
+ MockGateway.MOCK_GET_CLASS_METHOD = false;
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static synchronized <T> T createMock(Class<T> type, Method... methods) {
+ return doMock(type, false, new DefaultMockStrategy(), null, methods);
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @return the mock object.
+ */
+ public static synchronized <T> T createMock(Class<T> type) {
+ return doMock(type, false, new DefaultMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods
+ * and invokes a specific constructor.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArgs The constructor arguments that will be used to invoke a
+ * special constructor.
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static <T> T createMock(Class<T> type, ConstructorArgs constructorArgs, Method... methods) {
+ return doMock(type, false, new DefaultMockStrategy(), constructorArgs, methods);
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods
+ * and invokes a specific constructor based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @return the mock object.
+ */
+ public static <T> T createMock(Class<T> type, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new DefaultMockStrategy(), constructorArgs, (Method[]) null);
+ }
+
+ /**
+ * Creates a strict mock object that supports mocking of final and native
+ * methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static synchronized <T> T createStrictMock(Class<T> type, Method... methods) {
+ return doMock(type, false, new StrictMockStrategy(), null, methods);
+ }
+
+ /**
+ * Creates a strict mock object that supports mocking of final and native
+ * methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @return the mock object.
+ */
+ public static synchronized <T> T createStrictMock(Class<T> type) {
+ return doMock(type, false, new StrictMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * Creates a nice mock object that supports mocking of final and native
+ * methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static synchronized <T> T createNiceMock(Class<T> type, Method... methods) {
+ return doMock(type, false, new NiceMockStrategy(), null, methods);
+ }
+
+ /**
+ * Creates a nice mock object that supports mocking of final and native
+ * methods.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @return the mock object.
+ */
+ public static synchronized <T> T createNiceMock(Class<T> type) {
+ return doMock(type, false, new NiceMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * Creates a strict mock object that supports mocking of final and native
+ * methods and invokes a specific constructor.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArgs The constructor arguments that will be used to invoke a
+ * special constructor.
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static <T> T createStrictMock(Class<T> type, ConstructorArgs constructorArgs, Method... methods) {
+ return doMock(type, false, new StrictMockStrategy(), constructorArgs, methods);
+ }
+
+ /**
+ * Creates a nice mock object that supports mocking of final and native
+ * methods and invokes a specific constructor.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArgs The constructor arguments that will be used to invoke a
+ * special constructor.
+ * @param methods optionally what methods to mock
+ * @return the mock object.
+ */
+ public static <T> T createNiceMock(Class<T> type, ConstructorArgs constructorArgs, Method... methods) {
+ return doMock(type, false, new NiceMockStrategy(), constructorArgs, methods);
+ }
+
+ /**
+ * Creates a strict mock object that supports mocking of final and native
+ * methods and invokes a specific constructor based on the supplied argument
+ * values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @return the mock object.
+ */
+ public static <T> T createStrictMock(Class<T> type, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new StrictMockStrategy(), constructorArgs, (Method[]) null);
+ }
+
+ /**
+ * Creates a nice mock object that supports mocking of final and native
+ * methods and invokes a specific constructor based on the supplied argument
+ * values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @return the mock object.
+ */
+ public static <T> T createNiceMock(Class<T> type, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new NiceMockStrategy(), constructorArgs, (Method[]) null);
+ }
+
+ /**
+ * Enable static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ * @param methods optionally what methods to mock
+ */
+ public static synchronized void mockStatic(Class<?> type, Method... methods) {
+ doMock(type, true, new DefaultMockStrategy(), null, methods);
+ }
+
+ /**
+ * Enable static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ */
+ public static synchronized void mockStatic(Class<?> type) {
+ doMock(type, true, new DefaultMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * Enable strict static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ * @param methods optionally what methods to mock
+ */
+ public static synchronized void mockStaticStrict(Class<?> type, Method... methods) {
+ doMock(type, true, new StrictMockStrategy(), null, methods);
+ }
+
+ /**
+ * Enable strict static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ */
+ public static synchronized void mockStaticStrict(Class<?> type) {
+ doMock(type, true, new StrictMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * Enable nice static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ * @param methods optionally what methods to mock
+ */
+ public static synchronized void mockStaticNice(Class<?> type, Method... methods) {
+ doMock(type, true, new NiceMockStrategy(), null, methods);
+ }
+
+ /**
+ * Enable nice static mocking for a class.
+ *
+ * @param type the class to enable static mocking
+ */
+ public static synchronized void mockStaticNice(Class<?> type) {
+ doMock(type, true, new NiceMockStrategy(), null, (Method[]) null);
+ }
+
+ /**
+ * A utility method that may be used to specify several methods that should
+ * <i>not</i> be mocked in an easy manner (by just passing in the method
+ * names of the method you wish <i>not</i> to mock). Note that you cannot
+ * uniquely specify a method to exclude using this method if there are
+ * several methods with the same name in <code>type</code>. This method will
+ * mock ALL methods that doesn't match the supplied name(s) regardless of
+ * parameter types and signature. If this is not the case you should
+ * fall-back on using the {@link #createMock(Class, Method...)} method
+ * instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createPartialMockForAllMethodsExcept(Class<T> type, String... methodNames) {
+ if (methodNames != null && methodNames.length == 0) {
+ return createMock(type);
+ }
+
+ return createMock(type, WhiteboxImpl.getAllMethodExcept(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to specify several methods that should
+ * <i>not</i> be nicely mocked in an easy manner (by just passing in the
+ * method names of the method you wish <i>not</i> to mock). Note that you
+ * cannot uniquely specify a method to exclude using this method if there
+ * are several methods with the same name in <code>type</code>. This method
+ * will mock ALL methods that doesn't match the supplied name(s) regardless
+ * of parameter types and signature. If this is not the case you should
+ * fall-back on using the {@link #createMock(Class, Method...)} method
+ * instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createNicePartialMockForAllMethodsExcept(Class<T> type, String... methodNames) {
+ if (methodNames != null && methodNames.length == 0) {
+ return createNiceMock(type);
+ }
+
+ return createNiceMock(type, WhiteboxImpl.getAllMethodExcept(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to specify several methods that should
+ * <i>not</i> be strictly mocked in an easy manner (by just passing in the
+ * method names of the method you wish <i>not</i> to mock). Note that you
+ * cannot uniquely specify a method to exclude using this method if there
+ * are several methods with the same name in <code>type</code>. This method
+ * will mock ALL methods that doesn't match the supplied name(s) regardless
+ * of parameter types and signature. If this is not the case you should
+ * fall-back on using the {@link #createMock(Class, Method...)} method
+ * instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createStrictPartialMockForAllMethodsExcept(Class<T> type, String... methodNames) {
+ if (methodNames != null && methodNames.length == 0) {
+ return createStrictMock(type);
+ }
+
+ return createStrictMock(type, WhiteboxImpl.getAllMethodExcept(type, methodNames));
+ }
+
+ /**
+ * Mock all methods of a class except for a specific one. Use this method
+ * only if you have several overloaded methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToExclude The name of the method not to mock.
+ * @param firstArgumentType The type of the first parameter of the method not to mock
+ * @param moreTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createPartialMockForAllMethodsExcept(Class<T> type, String methodNameToExclude,
+ Class<?> firstArgumentType, Class<?>... moreTypes) {
+ /*
+ * The reason why we've split the first and "additional types" is
+ * because it should not intervene with the mockAllExcept(type,
+ * String...methodNames) method.
+ */
+ final Class<?>[] argumentTypes = mergeArgumentTypes(firstArgumentType, moreTypes);
+
+ return createMock(type, WhiteboxImpl.getAllMetodsExcept(type, methodNameToExclude, argumentTypes));
+ }
+
+ /**
+ * Mock all methods of a class except for a specific one nicely. Use this
+ * method only if you have several overloaded methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToExclude The name of the method not to mock.
+ * @param firstArgumentType The type of the first parameter of the method not to mock
+ * @param moreTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createNicePartialMockForAllMethodsExcept(Class<T> type,
+ String methodNameToExclude, Class<?> firstArgumentType, Class<?>... moreTypes) {
+ /*
+ * The reason why we've split the first and "additional types" is
+ * because it should not intervene with the mockAllExcept(type,
+ * String...methodNames) method.
+ */
+ final Class<?>[] argumentTypes = mergeArgumentTypes(firstArgumentType, moreTypes);
+
+ return createNiceMock(type, WhiteboxImpl.getAllMetodsExcept(type, methodNameToExclude, argumentTypes));
+ }
+
+ /**
+ * Mock all methods of a class except for a specific one strictly. Use this
+ * method only if you have several overloaded methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToExclude The name of the method not to mock.
+ * @param firstArgumentType The type of the first parameter of the method not to mock
+ * @param moreTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createStrictPartialMockForAllMethodsExcept(Class<T> type,
+ String methodNameToExclude, Class<?> firstArgumentType, Class<?>... moreTypes) {
+ /*
+ * The reason why we've split the first and "additional types" is
+ * because it should not intervene with the mockAllExcept(type,
+ * String...methodNames) method.
+ */
+ final Class<?>[] argumentTypes = mergeArgumentTypes(firstArgumentType, moreTypes);
+
+ return createStrictMock(type, WhiteboxImpl.getAllMetodsExcept(type, methodNameToExclude, argumentTypes));
+ }
+
+ /**
+ * Mock a single specific method. Use this to handle overloaded methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToMock The name of the method to mock
+ * @param firstArgumentType The type of the first parameter of the method to mock
+ * @param additionalArgumentTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createPartialMock(Class<T> type, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ return doMockSpecific(type, new DefaultMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * Strictly mock a single specific method. Use this to handle overloaded
+ * methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToMock The name of the method to mock
+ * @param firstArgumentType The type of the first parameter of the method to mock
+ * @param additionalArgumentTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createStrictPartialMock(Class<T> type, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ return doMockSpecific(type, new StrictMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * Nicely mock a single specific method. Use this to handle overloaded
+ * methods.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNameToMock The name of the method to mock
+ * @param firstArgumentType The type of the first parameter of the method to mock
+ * @param additionalArgumentTypes Optionally more parameter types that defines the method. Note
+ * that this is only needed to separate overloaded methods.
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createNicePartialMock(Class<T> type, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ return doMockSpecific(type, new NiceMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * Mock a single static method.
+ *
+ * @param clazz The class where the method is specified in.
+ * @param methodNameToMock The first argument
+ * @param firstArgumentType The first argument type.
+ * @param additionalArgumentTypes Optional additional argument types.
+ */
+ public static synchronized void mockStaticPartial(Class<?> clazz, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ doMockSpecific(clazz, new DefaultMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * Mock a single static method (strict).
+ *
+ * @param clazz The class where the method is specified in.
+ * @param methodNameToMock The first argument
+ * @param firstArgumentType The first argument type.
+ * @param additionalArgumentTypes Optional additional argument types.
+ */
+ public static synchronized void mockStaticPartialStrict(Class<?> clazz, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ doMockSpecific(clazz, new StrictMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * Mock a single static method (nice).
+ *
+ * @param clazz The class where the method is specified in.
+ * @param methodNameToMock The first argument
+ * @param firstArgumentType The first argument type.
+ * @param additionalArgumentTypes Optional additional argument types.
+ */
+ public static synchronized void mockStaticPartialNice(Class<?> clazz, String methodNameToMock,
+ Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ doMockSpecific(clazz, new NiceMockStrategy(), new String[]{methodNameToMock}, null,
+ mergeArgumentTypes(firstArgumentType, additionalArgumentTypes));
+ }
+
+ /**
+ * A utility method that may be used to mock several <b>static</b> methods
+ * in an easy way (by just passing in the method names of the method you
+ * wish to mock). Note that you cannot uniquely specify a method to mock
+ * using this method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #mockStatic(Class, Method...)} method instead.
+ *
+ * @param clazz The class that contains the static methods that should be
+ * mocked.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #mockStatic(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ */
+ public static synchronized void mockStaticPartial(Class<?> clazz, String... methodNames) {
+ mockStatic(clazz, Whitebox.getMethods(clazz, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several <b>static</b> methods
+ * (strict) in an easy way (by just passing in the method names of the
+ * method you wish to mock). Note that you cannot uniquely specify a method
+ * to mock using this method if there are several methods with the same name
+ * in <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #mockStaticStrict(Class, Method...)} method instead.
+ *
+ * @param clazz The class that contains the static methods that should be
+ * mocked.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #mockStatic(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ */
+ public static synchronized void mockStaticPartialStrict(Class<?> clazz, String... methodNames) {
+ mockStaticStrict(clazz, Whitebox.getMethods(clazz, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several <b>static</b> methods
+ * (nice) in an easy way (by just passing in the method names of the method
+ * you wish to mock). Note that you cannot uniquely specify a method to mock
+ * using this method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #mockStaticStrict(Class, Method...)} method instead.
+ *
+ * @param clazz The class that contains the static methods that should be
+ * mocked.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #mockStatic(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ */
+ public static synchronized void mockStaticPartialNice(Class<?> clazz, String... methodNames) {
+ mockStaticNice(clazz, Whitebox.getMethods(clazz, methodNames));
+ }
+
+ static <T> T doMockSpecific(Class<T> type, MockStrategy mockStrategy, String[] methodNamesToMock,
+ ConstructorArgs constructorArgs, Class<?>... argumentTypes) {
+ List<Method> methods = new LinkedList<Method>();
+ for (String methodName : methodNamesToMock) {
+ methods.add(WhiteboxImpl.findMethodOrThrowException(type, methodName, argumentTypes));
+ }
+
+ final Method[] methodArray = methods.toArray(new Method[0]);
+ if (WhiteboxImpl.areAllMethodsStatic(methodArray)) {
+ if (mockStrategy instanceof DefaultMockStrategy) {
+ mockStatic(type, methodArray);
+ } else if (mockStrategy instanceof StrictMockStrategy) {
+ mockStaticStrict(type, methodArray);
+ } else {
+ mockStaticNice(type, methodArray);
+ }
+ return null;
+ }
+
+ T mock = null;
+ if (mockStrategy instanceof DefaultMockStrategy) {
+ mock = createMock(type, constructorArgs, methodArray);
+ } else if (mockStrategy instanceof StrictMockStrategy) {
+ mock = createStrictMock(type, constructorArgs, methodArray);
+ } else {
+ mock = createNiceMock(type, constructorArgs, methodArray);
+ }
+
+ return mock;
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock).
+ * Note that you cannot uniquely specify a method to mock using this method
+ * if there are several methods with the same name in <code>type</code>.
+ * This method will mock ALL methods that match the supplied name regardless
+ * of parameter types and signature. If this is the case you should
+ * fall-back on using the {@link #createMock(Class, Method...)} method
+ * instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createPartialMock(Class<T> type, String... methodNames) {
+ return createMock(type, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock).
+ * Note that you cannot uniquely specify a method to mock using this method
+ * if there are several methods with the same name in <code>type</code>.
+ * This method will mock ALL methods that match the supplied name regardless
+ * of parameter types and signature. If this is the case you should
+ * fall-back on using the {@link #createMock(Class, Method...)} method
+ * instead.
+ * <p/>
+ * With this method you can specify where the class hierarchy the methods
+ * are located. This is useful in, for example, situations where class A
+ * extends B and both have a method called "mockMe" (A overrides B's mockMe
+ * method) and you like to specify the only the "mockMe" method in B should
+ * be mocked. "mockMe" in A should be left intact. In this case you should
+ * do:
+ * <p/>
+ * <pre>
+ * A tested = createPartialMock(A.class, B.class, "mockMe");
+ * </pre>
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param where Where in the class hierarchy the methods resides.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createPartialMock(Class<T> type, Class<? super T> where, String... methodNames) {
+ return createMock(type, Whitebox.getMethods(where, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to strictly mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Note that you cannot uniquely specify a method to mock using this
+ * method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #createMock(Class, Method...)} method instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createStrictPartialMock(Class<T> type, String... methodNames) {
+ return createStrictMock(type, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to strictly mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Note that you cannot uniquely specify a method to mock using this
+ * method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #createMock(Class, Method...)} method instead.
+ * <p/>
+ * With this method you can specify where the class hierarchy the methods
+ * are located. This is useful in, for example, situations where class A
+ * extends B and both have a method called "mockMe" (A overrides B's mockMe
+ * method) and you like to specify the only the "mockMe" method in B should
+ * be mocked. "mockMe" in A should be left intact. In this case you should
+ * do:
+ * <p/>
+ * <pre>
+ * A tested = createPartialMockStrict(A.class, B.class, "mockMe");
+ * </pre>
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param where Where in the class hierarchy the methods resides.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createStrictPartialMock(Class<T> type, Class<? super T> where,
+ String... methodNames) {
+ return createStrictMock(type, Whitebox.getMethods(where, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Note that you cannot uniquely specify a method to mock using this
+ * method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #createMock(Class, Method...)} method instead.
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createNicePartialMock(Class<T> type, String... methodNames) {
+ return createNiceMock(type, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Note that you cannot uniquely specify a method to mock using this
+ * method if there are several methods with the same name in
+ * <code>type</code>. This method will mock ALL methods that match the
+ * supplied name regardless of parameter types and signature. If this is the
+ * case you should fall-back on using the
+ * {@link #createMock(Class, Method...)} method instead.
+ * <p/>
+ * With this method you can specify where the class hierarchy the methods
+ * are located. This is useful in, for example, situations where class A
+ * extends B and both have a method called "mockMe" (A overrides B's mockMe
+ * method) and you like to specify the only the "mockMe" method in B should
+ * be mocked. "mockMe" in A should be left intact. In this case you should
+ * do:
+ * <p/>
+ * <pre>
+ * A tested = createPartialMockNice(A.class, B.class, "mockMe");
+ * </pre>
+ *
+ * @param <T> The type of the mock.
+ * @param type The type that'll be used to create a mock instance.
+ * @param where Where in the class hierarchy the methods resides.
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return A mock object of type <T>.
+ */
+ public static synchronized <T> T createNicePartialMock(Class<T> type, Class<? super T> where, String... methodNames) {
+ return createNiceMock(type, Whitebox.getMethods(where, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock). The
+ * mock object created will support mocking of final methods and invokes the
+ * default constructor (even if it's private).
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return the mock object.
+ */
+ public static <T> T createPartialMockAndInvokeDefaultConstructor(Class<T> type, String... methodNames)
+ throws Exception {
+ return createMock(type, new ConstructorArgs(Whitebox.getConstructor(type)),
+ Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). The mock object created will support mocking of final methods and
+ * invokes the default constructor (even if it's private).
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return the mock object.
+ */
+ public static <T> T createNicePartialMockAndInvokeDefaultConstructor(Class<T> type, String... methodNames)
+ throws Exception {
+ return createNiceMock(type, new ConstructorArgs(Whitebox.getConstructor(type)),
+ Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to strictly mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). The mock object created will support mocking of final methods and
+ * invokes the default constructor (even if it's private).
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @return the mock object.
+ */
+ public static <T> T createStrictPartialMockAndInvokeDefaultConstructor(Class<T> type, String... methodNames)
+ throws Exception {
+ return createStrictMock(type, new ConstructorArgs(Whitebox.getConstructor(type)),
+ Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock). The
+ * mock object created will support mocking of final and native methods and
+ * invokes a specific constructor based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createPartialMock(Class<T> type, String[] methodNames, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new DefaultMockStrategy(), constructorArgs, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * * A utility method that may be used to strictly mock several methods in
+ * an easy way (by just passing in the method names of the method you wish
+ * to mock). The mock object created will support mocking of final and
+ * native methods and invokes a specific constructor based on the supplied
+ * argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createStrictPartialMock(Class<T> type, String[] methodNames, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new StrictMockStrategy(), constructorArgs, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). The mock object created will support mocking of final and native
+ * methods and invokes a specific constructor based on the supplied argument
+ * values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodNames The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createNicePartialMock(Class<T> type, String[] methodNames, Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMock(type, false, new NiceMockStrategy(), constructorArgs, Whitebox.getMethods(type, methodNames));
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock). Use
+ * this to handle overloaded methods. The mock object created will support
+ * mocking of final and native methods and invokes a specific constructor
+ * based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createPartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMockSpecific(type, new DefaultMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * A utility method that may be used to strictly mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Use this to handle overloaded methods. The mock object created
+ * will support mocking of final and native methods and invokes a specific
+ * constructor based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createStrictPartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMockSpecific(type, new StrictMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Use this to handle overloaded methods. The mock object created
+ * will support mocking of final and native methods and invokes a specific
+ * constructor based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor. (optional)
+ * @return the mock object.
+ */
+ public static <T> T createNicePartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object... constructorArguments) {
+ Constructor<?> constructor = WhiteboxImpl.findUniqueConstructorOrThrowException(type, constructorArguments);
+ ConstructorArgs constructorArgs = new ConstructorArgs(constructor, constructorArguments);
+ return doMockSpecific(type, new NiceMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * A utility method that may be used to mock several methods in an easy way
+ * (by just passing in the method names of the method you wish to mock). Use
+ * this to handle overloaded methods <i>and</i> overloaded constructors. The
+ * mock object created will support mocking of final and native methods and
+ * invokes a specific constructor based on the supplied argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @param constructorParameterTypes Parameter types that defines the constructor that should be
+ * invoked. Note that this is only needed to separate overloaded
+ * constructors.
+ * @return the mock object.
+ */
+ public static <T> T createPartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object[] constructorArguments, Class<?>[] constructorParameterTypes) {
+ ConstructorArgs constructorArgs = new ConstructorArgs(Whitebox.getConstructor(type, constructorParameterTypes),
+ constructorArguments);
+ return doMockSpecific(type, new DefaultMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * A utility method that may be used to strictly mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Use this to handle overloaded methods <i>and</i> overloaded
+ * constructors. The mock object created will support mocking of final and
+ * native methods and invokes a specific constructor based on the supplied
+ * argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @param constructorParameterTypes Parameter types that defines the constructor that should be
+ * invoked. Note that this is only needed to separate overloaded
+ * constructors.
+ * @return the mock object.
+ */
+ public static <T> T createStrictPartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object[] constructorArguments, Class<?>[] constructorParameterTypes) {
+ ConstructorArgs constructorArgs = new ConstructorArgs(Whitebox.getConstructor(type, constructorParameterTypes),
+ constructorArguments);
+ return doMockSpecific(type, new StrictMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * A utility method that may be used to nicely mock several methods in an
+ * easy way (by just passing in the method names of the method you wish to
+ * mock). Use this to handle overloaded methods <i>and</i> overloaded
+ * constructors. The mock object created will support mocking of final and
+ * native methods and invokes a specific constructor based on the supplied
+ * argument values.
+ *
+ * @param <T> the type of the mock object
+ * @param type the type of the mock object
+ * @param methodName The names of the methods that should be mocked. If
+ * <code>null</code>, then this method will have the same effect
+ * as just calling {@link #createMock(Class, Method...)} with the
+ * second parameter as <code>new Method[0]</code> (i.e. all
+ * methods in that class will be mocked).
+ * @param methodParameterTypes Parameter types that defines the method. Note that this is
+ * only needed to separate overloaded methods.
+ * @param constructorArguments The constructor arguments that will be used to invoke a
+ * certain constructor.
+ * @param constructorParameterTypes Parameter types that defines the constructor that should be
+ * invoked. Note that this is only needed to separate overloaded
+ * constructors.
+ * @return the mock object.
+ */
+ public static <T> T createNicePartialMock(Class<T> type, String methodName, Class<?>[] methodParameterTypes,
+ Object[] constructorArguments, Class<?>[] constructorParameterTypes) {
+ ConstructorArgs constructorArgs = new ConstructorArgs(Whitebox.getConstructor(type, constructorParameterTypes),
+ constructorArguments);
+ return doMockSpecific(type, new NiceMockStrategy(), new String[]{methodName}, constructorArgs,
+ methodParameterTypes);
+ }
+
+ /**
+ * Used to specify expectations on private static methods. If possible use
+ * variant with only method name.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Class<?> clazz, Method method,
+ Object... arguments) throws Exception {
+ return doExpectPrivate(clazz, method, arguments);
+ }
+
+ /**
+ * Used to specify expectations on private methods. If possible use variant
+ * with only method name.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, Method method,
+ Object... arguments) throws Exception {
+ return doExpectPrivate(instance, method, arguments);
+ }
+
+ /**
+ * Used to specify expectations on private methods. Use this method to
+ * handle overloaded methods.
+ */
+ @SuppressWarnings("all")
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
+ Class<?>[] parameterTypes, Object... arguments) throws Exception {
+
+ if (arguments == null) {
+ arguments = new Object[0];
+ }
+
+ if (instance == null) {
+ throw new IllegalArgumentException("instance cannot be null.");
+ } else if (arguments.length != parameterTypes.length) {
+ throw new IllegalArgumentException(
+ "The length of the arguments must be equal to the number of parameter types.");
+ }
+
+ Method foundMethod = Whitebox.getMethod(instance.getClass(), methodName, parameterTypes);
+
+ WhiteboxImpl.throwExceptionIfMethodWasNotFound(instance.getClass(), methodName, foundMethod, parameterTypes);
+
+ return doExpectPrivate(instance, foundMethod, arguments);
+ }
+
+ /**
+ * Used to specify expectations on methods using the method name. Works on
+ * for example private or package private methods.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
+ Object... arguments) throws Exception {
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance or class cannot be null.");
+ }
+
+ return expectPrivate(instance, methodName, Whitebox.getType(instance), arguments);
+ }
+
+ /**
+ * Used to specify expectations on methods without specifying a method name.
+ * Works on for example private or package private methods. PowerMock tries
+ * to find a unique method to expect based on the argument parameters. If
+ * PowerMock is unable to locate a unique method you need to revert to using
+ * {@link #expectPrivate(Object, String, Object...)}.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, Object... arguments)
+ throws Exception {
+ return expectPrivate(instance, null, Whitebox.getType(instance), arguments);
+ }
+
+ /**
+ * Used to specify expectations on methods using the method name at a
+ * specific place in the class hierarchy (specified by the
+ * <code>where</code> parameter). Works on for example private or package
+ * private methods.
+ * <p/>
+ * Use this for overloaded methods.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
+ Class<?> where, Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ if (instance == null) {
+ throw new IllegalArgumentException("Instance or class to expect cannot be null.");
+ }
+ Method[] methods = null;
+ if (methodName != null) {
+ if (parameterTypes == null) {
+ methods = Whitebox.getMethods(where, methodName);
+ } else {
+ methods = new Method[]{Whitebox.getMethod(where, methodName, parameterTypes)};
+ }
+ }
+ Method methodToExpect;
+ if (methods != null && methods.length == 1) {
+ methodToExpect = methods[0];
+ } else {
+ methodToExpect = WhiteboxImpl.findMethodOrThrowException(instance, null, methodName, arguments);
+ }
+
+ return doExpectPrivate(instance, methodToExpect, arguments);
+ }
+
+ /**
+ * Used to specify expectations on methods using the method name at a
+ * specific place in the class hierarchy (specified by the
+ * <code>where</code> parameter). Works on for example private or package
+ * private methods.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectPrivate(Object instance, String methodName,
+ Class<?> where, Object... arguments) throws Exception {
+ return expectPrivate(instance, methodName, where, null, arguments);
+ }
+
+ /**
+ * This method just delegates to EasyMock class extensions
+ * {@link org.easymock.EasyMock#expectLastCall()} method.
+ *
+ * @return The expectation setter.
+ * @see org.easymock.EasyMock#expectLastCall()
+ */
+ public static synchronized IExpectationSetters<Object> expectLastCall() {
+ return org.easymock.EasyMock.expectLastCall();
+ }
+
+ /**
+ * Sometimes it is useful to allow replay and verify on non-mocks. For
+ * example when using partial mocking in some tests and no mocking in other
+ * test-methods, but using the same setUp and tearDown.
+ */
+ public static synchronized void niceReplayAndVerify() {
+ MockRepository.putAdditionalState(NICE_REPLAY_AND_VERIFY_KEY, true);
+ }
+
+ /**
+ * Test if a object is a mock created by EasyMock or not.
+ */
+ private static boolean isEasyMocked(Object mock) {
+ return Enhancer.isEnhanced(mock.getClass()) || Proxy.isProxyClass(mock.getClass());
+ }
+
+ /**
+ * Replay all classes and mock objects known by PowerMock. This includes all
+ * classes that are prepared for test using the {@link PrepareForTest} or
+ * {@link PrepareOnlyThisForTest} annotations and all classes that have had
+ * their static initializers removed by using the
+ * {@link SuppressStaticInitializationFor} annotation. It also includes all
+ * mock instances created by PowerMock such as those created or used by
+ * {@link #createMock(Class, Method...)},
+ * {@link #mockStatic(Class, Method...)},
+ * {@link #expectNew(Class, Object...)},
+ * {@link #createPartialMock(Class, String...)} etc.
+ * <p/>
+ * To make it easy to pass in additional mocks <i>not</i> created by the
+ * PowerMock API you can optionally specify them as <tt>additionalMocks</tt>
+ * . These are typically those mock objects you have created using pure
+ * EasyMock or EasyMock class extensions. No additional mocks needs to be
+ * specified if you're only using PowerMock API methods.
+ * <p/>
+ * Note that the <tt>additionalMocks</tt> are also automatically verified
+ * when invoking the {@link #verifyAll()} method.
+ *
+ * @param additionalMocks Mocks not created by the PowerMock API. These are typically
+ * those mock objects you have created using pure EasyMock or
+ * EasyMock class extensions.
+ */
+ public static synchronized void replayAll(Object... additionalMocks) {
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(additionalMocks);
+
+ for (Object classToReplayOrVerify : MockRepository.getObjectsToAutomaticallyReplayAndVerify()) {
+ replay(classToReplayOrVerify);
+ }
+ }
+
+ /**
+ * Reset all classes and mock objects known by PowerMock. This includes all
+ * classes that are prepared for test using the {@link PrepareForTest} or
+ * {@link PrepareOnlyThisForTest} annotations and all classes that have had
+ * their static initializers removed by using the
+ * {@link SuppressStaticInitializationFor} annotation. It also includes all
+ * mock instances created by PowerMock such as those created or used by
+ * {@link #createMock(Class, Method...)},
+ * {@link #mockStatic(Class, Method...)},
+ * {@link #expectNew(Class, Object...)},
+ * {@link #createPartialMock(Class, String...)} etc.
+ * <p/>
+ * To make it easy to pass in additional mocks <i>not</i> created by the
+ * PowerMock API you can optionally specify them as <tt>additionalMocks</tt>
+ * . These are typically those mock objects you have created using pure
+ * EasyMock or EasyMock class extensions. No additional mocks needs to be
+ * specified if you're only using PowerMock API methods.
+ *
+ * @param additionalMocks Mocks not created by the PowerMock API. These are typically
+ * those mock objects you have created using pure EasyMock or
+ * EasyMock class extensions.
+ */
+ public static synchronized void resetAll(Object... additionalMocks) {
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(additionalMocks);
+
+ for (Object classToReplayOrVerify : MockRepository.getObjectsToAutomaticallyReplayAndVerify()) {
+ reset(classToReplayOrVerify);
+ }
+ }
+
+ /**
+ * Reset a list of class mocks.
+ */
+ public static synchronized void reset(Class<?>... classMocks) {
+ for (Class<?> type : classMocks) {
+ final MethodInvocationControl invocationHandler = MockRepository.getStaticMethodInvocationControl(type);
+ if (invocationHandler != null) {
+ invocationHandler.reset();
+ }
+ NewInvocationControl<?> newInvocationControl = MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ try {
+ newInvocationControl.reset();
+ } catch (AssertionError e) {
+ NewInvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+ }
+ }
+ }
+
+ /**
+ * Reset a list of mock objects or classes.
+ */
+ public static synchronized void reset(Object... mocks) {
+ try {
+ for (Object mock : mocks) {
+ if (mock instanceof Class<?>) {
+ reset((Class<?>) mock);
+ } else {
+ MethodInvocationControl invocationControl = MockRepository.getInstanceMethodInvocationControl(mock);
+ if (invocationControl != null) {
+ invocationControl.reset();
+ } else {
+ if (isNiceReplayAndVerifyMode() && !isEasyMocked(mock)) {
+ // ignore non-mock
+ } else {
+ /*
+ * Delegate to easy mock class extension if we have
+ * no handler registered for this object.
+ */
+ try {
+ org.easymock.EasyMock.reset(mock);
+ } catch (RuntimeException e) {
+ throw new RuntimeException(mock + " is not a mock object", e);
+ }
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ MockRepository.putAdditionalState(NICE_REPLAY_AND_VERIFY_KEY, false);
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ } else if (t instanceof Error) {
+ throw (Error) t;
+ }
+ throw new RuntimeException(t);
+ }
+ }
+
+ /**
+ * Verify all classes and mock objects known by PowerMock. This includes all
+ * classes that are prepared for test using the {@link PrepareForTest} or
+ * {@link PrepareOnlyThisForTest} annotations and all classes that have had
+ * their static initializers removed by using the
+ * {@link SuppressStaticInitializationFor} annotation. It also includes all
+ * mock instances created by PowerMock such as those created or used by
+ * {@link #createMock(Class, Method...)},
+ * {@link #mockStatic(Class, Method...)},
+ * {@link #expectNew(Class, Object...)},
+ * {@link #createPartialMock(Class, String...)} etc.
+ * <p/>
+ * Note that all <tt>additionalMocks</tt> passed to the
+ * {@link #replayAll(Object...)} method are also verified here
+ * automatically.
+ */
+ public static synchronized void verifyAll() {
+ for (Object classToReplayOrVerify : MockRepository.getObjectsToAutomaticallyReplayAndVerify()) {
+ verify(classToReplayOrVerify);
+ }
+ }
+
+ /**
+ * Switches the mocks or classes to replay mode. Note that you must use this
+ * method when using PowerMock!
+ *
+ * @param mocks mock objects or classes loaded by PowerMock.
+ * @throws Exception If something unexpected goes wrong.
+ */
+ public static synchronized void replay(Object... mocks) {
+ try {
+ for (Object mock : mocks) {
+ if (mock instanceof Class<?>) {
+ replay((Class<?>) mock);
+ } else {
+ MethodInvocationControl invocationControl = MockRepository.getInstanceMethodInvocationControl(mock);
+ if (invocationControl != null) {
+ invocationControl.replay();
+ } else {
+ if (isNiceReplayAndVerifyMode() && !isEasyMocked(mock)) {
+ // ignore non-mock
+ } else {
+ /*
+ * Delegate to easy mock class extension if we have
+ * no handler registered for this object.
+ */
+ try {
+ org.easymock.EasyMock.replay(mock);
+ } catch (RuntimeException e) {
+ throw new RuntimeException(mock + " is not a mock object", e);
+ }
+ }
+ }
+ }
+ }
+ } catch (Throwable t) {
+ MockRepository.putAdditionalState(NICE_REPLAY_AND_VERIFY_KEY, false);
+ if (t instanceof RuntimeException) {
+ throw (RuntimeException) t;
+ } else if (t instanceof Error) {
+ throw (Error) t;
+ }
+ throw new RuntimeException(t);
+ }
+ }
+
+ /**
+ * Switches the mocks or classes to verify mode. Note that you must use this
+ * method when using PowerMock!
+ *
+ * @param objects mock objects or classes loaded by PowerMock.
+ */
+ public static synchronized void verify(Object... objects) {
+ for (Object mock : objects) {
+ if (mock instanceof Class<?>) {
+ verifyClass((Class<?>) mock);
+ } else {
+ MethodInvocationControl invocationControl = MockRepository.getInstanceMethodInvocationControl(mock);
+ if (invocationControl != null) {
+ invocationControl.verify();
+ } else {
+ if (isNiceReplayAndVerifyMode() && !isEasyMocked(mock)) {
+ // ignore non-mock
+ } else {
+ /*
+ * Delegate to easy mock class extension if we have no
+ * handler registered for this object.
+ */
+ try {
+ org.easymock.EasyMock.verify(mock);
+ } catch (RuntimeException e) {
+ throw new RuntimeException(mock + " is not a mock object", e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Convenience method for createMock followed by expectNew.
+ *
+ * @param type The class that should be mocked.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createMockAndExpectNew(Class<T> type, Object... arguments) throws Exception {
+ T mock = createMock(type);
+ expectNew(type, arguments).andReturn(mock);
+ return mock;
+ }
+
+ /**
+ * Convenience method for createMock followed by expectNew when PowerMock
+ * cannot determine which constructor to use automatically. This happens
+ * when you have one constructor taking a primitive type and another one
+ * taking the wrapper type of the primitive. For example <code>int</code>
+ * and <code>Integer</code>.
+ *
+ * @param type The class that should be mocked.
+ * @param parameterTypes The constructor parameter types.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createMockAndExpectNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ T mock = createMock(type);
+ expectNew(type, parameterTypes, arguments).andReturn(mock);
+ return mock;
+ }
+
+ /**
+ * Convenience method for createNiceMock followed by expectNew.
+ *
+ * @param type The class that should be mocked.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createNiceMockAndExpectNew(Class<T> type, Object... arguments) throws Exception {
+ T mock = createNiceMock(type);
+ IExpectationSetters<T> expectationSetters = expectNiceNew(type, arguments);
+ if (expectationSetters != null) {
+ expectationSetters.andReturn(mock);
+ }
+ return mock;
+ }
+
+ /**
+ * Convenience method for createNiceMock followed by expectNew when
+ * PowerMock cannot determine which constructor to use automatically. This
+ * happens when you have one constructor taking a primitive type and another
+ * one taking the wrapper type of the primitive. For example
+ * <code>int</code> and <code>Integer</code>.
+ *
+ * @param type The class that should be mocked.
+ * @param parameterTypes The constructor parameter types.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createNiceMockAndExpectNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ T mock = createNiceMock(type);
+ IExpectationSetters<T> expectationSetters = expectNiceNew(type, parameterTypes, arguments);
+ if (expectationSetters != null) {
+ expectationSetters.andReturn(mock);
+ }
+ return mock;
+ }
+
+ /**
+ * Convenience method for createStrictMock followed by expectNew.
+ *
+ * @param type The class that should be mocked.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createStrictMockAndExpectNew(Class<T> type, Object... arguments) throws Exception {
+ T mock = createStrictMock(type);
+ expectStrictNew(type, arguments).andReturn(mock);
+ return mock;
+ }
+
+ /**
+ * Convenience method for createStrictMock followed by expectNew when
+ * PowerMock cannot determine which constructor to use automatically. This
+ * happens when you have one constructor taking a primitive type and another
+ * one taking the wrapper type of the primitive. For example
+ * <code>int</code> and <code>Integer</code>.
+ *
+ * @param type The class that should be mocked.
+ * @param parameterTypes The constructor parameter types.
+ * @param arguments The constructor arguments.
+ * @return A mock object of the same type as the mock.
+ * @throws Exception
+ */
+ public static synchronized <T> T createStrictMockAndExpectNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ T mock = createStrictMock(type);
+ expectStrictNew(type, parameterTypes, arguments).andReturn(mock);
+ return mock;
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock. Note that you must replay
+ * the class when using this method since this behavior is part of the class
+ * mock.
+ * <p/>
+ * Use this method when you need to specify parameter types for the
+ * constructor when PowerMock cannot determine which constructor to use
+ * automatically. In most cases you should use
+ * {@link #expectNew(Class, Object...)} instead.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ return doExpectNew(type, new DefaultMockStrategy(), parameterTypes, arguments);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> IExpectationSetters<T> doExpectNew(Class<T> type, MockStrategy mockStrategy,
+ Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ if (type == null) {
+ throw new IllegalArgumentException("type cannot be null");
+ } else if (mockStrategy == null) {
+ throw new IllegalArgumentException("Internal error: Mock strategy cannot be null");
+ }
+
+ final boolean isNiceMock = mockStrategy instanceof NiceMockStrategy;
+
+ final Class<T> unmockedType = (Class<T>) WhiteboxImpl.getUnmockedType(type);
+ if (!isNiceMock) {
+ if (parameterTypes == null) {
+ WhiteboxImpl.findUniqueConstructorOrThrowException(type, arguments);
+ } else {
+ WhiteboxImpl.getConstructor(unmockedType, parameterTypes);
+ }
+ }
+
+ /*
+ * Check if this type has been mocked before
+ */
+ NewInvocationControl<IExpectationSetters<T>> newInvocationControl = (NewInvocationControl<IExpectationSetters<T>>) MockRepository
+ .getNewInstanceControl(unmockedType);
+ if (newInvocationControl == null) {
+ InvocationSubstitute<T> mock = doMock(InvocationSubstitute.class, false, mockStrategy, null,
+ (Method[]) null);
+ newInvocationControl = new NewInvocationControlImpl<T>(mock, type);
+ MockRepository.putNewInstanceControl(type, newInvocationControl);
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(WhiteboxImpl.getUnmockedType(type));
+ }
+
+ if (isNiceMock && (arguments == null || arguments.length == 0)) {
+ return null;
+ }
+ return newInvocationControl.expectSubstitutionLogic(arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock. Note that you must replay
+ * the class when using this method since this behavior is part of the class
+ * mock.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectNew(Class<T> type, Object... arguments)
+ throws Exception {
+ return doExpectNew(type, new DefaultMockStrategy(), null, arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations for private member
+ * (inner) classes, local or anonymous classes. For example you might want
+ * to throw an exception or return a mock. Note that you must replay the
+ * class when using this method since this behavior is part of the class
+ * mock.
+ *
+ * @param fullyQualifiedName The fully-qualified name of the inner/local/anonymous type to
+ * expect.
+ * @param arguments Optional number of arguments.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> IExpectationSetters<T> expectNew(String fullyQualifiedName, Object... arguments)
+ throws Exception {
+ final Class<?> forName = Class.forName(fullyQualifiedName);
+ return (IExpectationSetters<T>) doExpectNew(forName, new DefaultMockStrategy(), null, arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ * <p/>
+ * This method checks the order of constructor invocations.
+ * <p/>
+ * Note that you must replay the class when using this method since this
+ * behavior is part of the class mock.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectStrictNew(Class<T> type, Object... arguments)
+ throws Exception {
+ return doExpectNew(type, new StrictMockStrategy(), null, arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock. Note that you must replay
+ * the class when using this method since this behavior is part of the class
+ * mock.
+ * <p/>
+ * This method checks the order of constructor invocations.
+ * <p/>
+ * Use this method when you need to specify parameter types for the
+ * constructor when PowerMock cannot determine which constructor to use
+ * automatically. In most cases you should use
+ * {@link #expectNew(Class, Object...)} instead.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectStrictNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ return doExpectNew(type, new StrictMockStrategy(), parameterTypes, arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ * <p/>
+ * This method allows any number of calls to a new constructor without
+ * throwing an exception.
+ * <p/>
+ * Note that you must replay the class when using this method since this
+ * behavior is part of the class mock.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectNiceNew(Class<T> type, Object... arguments)
+ throws Exception {
+ return doExpectNew(type, new NiceMockStrategy(), null, arguments);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock. Note that you must replay
+ * the class when using this method since this behavior is part of the class
+ * mock.
+ * <p/>
+ * This method allows any number of calls to a new constructor without
+ * throwing an exception.
+ * <p/>
+ * Use this method when you need to specify parameter types for the
+ * constructor when PowerMock cannot determine which constructor to use
+ * automatically. In most cases you should use
+ * {@link #expectNew(Class, Object...)} instead.
+ */
+ public static synchronized <T> IExpectationSetters<T> expectNiceNew(Class<T> type, Class<?>[] parameterTypes,
+ Object... arguments) throws Exception {
+ return doExpectNew(type, new NiceMockStrategy(), parameterTypes, arguments);
+ }
+
+ /**
+ * Suppress constructor calls on specific constructors only.
+ *
+ * @deprecated Use {@link #suppress(Constructor[])} instead.
+ */
+ public static synchronized void suppressConstructor(Constructor<?>... constructors) {
+ SuppressCode.suppressConstructor(constructors);
+ }
+
+ /**
+ * This method can be used to suppress the code in a specific constructor.
+ *
+ * @param clazz The class where the constructor is located.
+ * @param parameterTypes The parameter types of the constructor to suppress.
+ * @deprecated Use {@link #suppress(Constructor)} instead.
+ */
+ public static synchronized void suppressSpecificConstructor(Class<?> clazz, Class<?>... parameterTypes) {
+ SuppressCode.suppressSpecificConstructor(clazz, parameterTypes);
+ }
+
+ /**
+ * Suppress all constructors in the given class and it's super classes.
+ *
+ * @param classes The classes whose constructors will be suppressed.
+ * @deprecated Use {@link #suppress(Constructor[])} instead.
+ */
+ public static synchronized void suppressConstructor(Class<?>... classes) {
+ SuppressCode.suppressConstructor(classes);
+ }
+
+ /**
+ * Suppress all constructors in the given class.
+ *
+ * @param clazz The classes whose constructors will be suppressed.
+ * @param excludePrivateConstructors optionally keep code in private constructors
+ * @deprecated Use {@link #suppress(Constructor[])} instead.
+ */
+ public static synchronized void suppressConstructor(Class<?> clazz, boolean excludePrivateConstructors) {
+ SuppressCode.suppressConstructor(clazz, excludePrivateConstructors);
+ }
+
+ /**
+ * Suppress specific fields. This works on both instance methods and static
+ * methods. Note that replay and verify are not needed as this is not part
+ * of a mock behavior.
+ *
+ * @deprecated Use {@link #suppress(Field[])} instead.
+ */
+ public static synchronized void suppressField(Field... fields) {
+ SuppressCode.suppressField(fields);
+ }
+
+ /**
+ * Suppress all fields for these classes.
+ *
+ * @deprecated Use {@link #suppress(Field[])} instead.
+ */
+ public static synchronized void suppressField(Class<?>[] classes) {
+ SuppressCode.suppressField(classes);
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param clazz The class whose methods will be suppressed.
+ * @param fieldNames The names of the methods that'll be suppressed. If field names
+ * are empty, <i>all</i> fields in the supplied class will be
+ * suppressed.
+ * @deprecated Use {@link #suppress(Field)} instead.
+ */
+ public static synchronized void suppressField(Class<?> clazz, String... fieldNames) {
+ SuppressCode.suppressField(clazz, fieldNames);
+ }
+
+ /**
+ * Suppress specific method calls on all types containing this method. This
+ * works on both instance methods and static methods. Note that replay and
+ * verify are not needed as this is not part of a mock behavior.
+ *
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Method... methods) {
+ SuppressCode.suppressMethod(methods);
+ }
+
+ /**
+ * Suppress all methods for these classes.
+ *
+ * @param cls The first class whose methods will be suppressed.
+ * @param additionalClasses Additional classes whose methods will be suppressed.
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Class<?> cls, Class<?>... additionalClasses) {
+ SuppressCode.suppressMethod(cls, additionalClasses);
+ }
+
+ /**
+ * Suppress all methods for these classes.
+ *
+ * @param classes Classes whose methods will be suppressed.
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Class<?>[] classes) {
+ SuppressCode.suppressMethod(classes);
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param clazz The class whose methods will be suppressed.
+ * @param methodName The first method to be suppress in class <code>clazz</code>.
+ * @param additionalMethodNames Additional methods to suppress in class <code>clazz</code>.
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String methodName, String... additionalMethodNames) {
+ SuppressCode.suppressMethod(clazz, methodName, additionalMethodNames);
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param clazz The class whose methods will be suppressed.
+ * @param methodNames Methods to suppress in class <code>clazz</code>.
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String[] methodNames) {
+ SuppressCode.suppressMethod(clazz, methodNames);
+ }
+
+ /**
+ * Suppress all methods for this class.
+ *
+ * @param clazz The class which methods will be suppressed.
+ * @param excludePrivateMethods optionally not suppress private methods
+ * @deprecated Use {@link #suppress(Method[])} instead.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, boolean excludePrivateMethods) {
+ SuppressCode.suppressMethod(clazz, excludePrivateMethods);
+ }
+
+ /**
+ * Suppress a specific method call. Use this for overloaded methods.
+ *
+ * @deprecated Use {@link #suppress(Method)} instead.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) {
+ SuppressCode.suppressMethod(clazz, methodName, parameterTypes);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T doMock(Class<T> type, boolean isStatic, MockStrategy mockStrategy,
+ ConstructorArgs constructorArgs, Method... methods) {
+ if (type == null) {
+ throw new IllegalArgumentException("The class to mock cannot be null");
+ }
+
+ /*
+ * Clear the EasyMock state after the test method is executed.
+ */
+ MockRepository.addAfterMethodRunner(new Runnable() {
+ @Override
+ public void run() {
+ LastControl.reportLastControl(null);
+ }
+ });
+
+ IMocksControl control = mockStrategy.createMockControl(type);
+ MockRepository.addAfterMethodRunner(new EasyMockStateCleaner());
+ T mock;
+ if (type.isInterface()) {
+ mock = control.createMock(type);
+ } else if (type.getName().startsWith("java.") && Modifier.isFinal(type.getModifiers())) {
+ Class<?> replicaType = createReplicaType(type, isStatic, constructorArgs);
+ final Object replica = doCreateMock(replicaType, constructorArgs, control, methods);
+ control = mockStrategy.createMockControl(replicaType);
+ MockInvocationHandler h = new MockInvocationHandler((MocksControl) control);
+ final Set<Method> methodsToMock = toSet(methods);
+ if (isStatic) {
+ MockRepository.putStaticMethodInvocationControl(type, new EasyMockMethodInvocationControl<Object>(h,
+ methodsToMock, replica));
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(type);
+ return null;
+ } else {
+ final T newInstance;
+ if (constructorArgs == null) {
+ newInstance = Whitebox.newInstance(type);
+ DefaultFieldValueGenerator.fillWithDefaultValues(newInstance);
+ } else {
+ try {
+ newInstance = (T) constructorArgs.getConstructor().newInstance(constructorArgs.getInitArgs());
+ } catch (Exception e) {
+ throw new RuntimeException("Internal error", e);
+ }
+ }
+ MockRepository.putInstanceMethodInvocationControl(newInstance,
+ new EasyMockMethodInvocationControl<Object>(h, methodsToMock, replica));
+ if (newInstance instanceof InvocationSubstitute<?> == false) {
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(newInstance);
+ }
+ return newInstance;
+ }
+ } else {
+ mock = doCreateMock(type, constructorArgs, control, methods);
+ }
+ MockInvocationHandler h = new MockInvocationHandler((MocksControl) control);
+ final Set<Method> methodsToMock = toSet(methods);
+ if (isStatic) {
+ MockRepository.putStaticMethodInvocationControl(type, new EasyMockMethodInvocationControl<T>(h,
+ methodsToMock, mock));
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(type);
+ } else {
+ MockRepository.putInstanceMethodInvocationControl(mock, new EasyMockMethodInvocationControl<T>(h,
+ methodsToMock));
+ if (mock instanceof InvocationSubstitute<?> == false) {
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(mock);
+ }
+ }
+ ClassLoader classLoader = mock.getClass().getClassLoader();
+ if (classLoader instanceof MockClassLoader) {
+ ((MockClassLoader) classLoader).cache(mock.getClass());
+ }
+ return mock;
+ }
+
+ private static <T> Class<?> createReplicaType(Class<T> type, boolean isStatic, ConstructorArgs constructorArgs) {
+ ClassReplicaCreator classReplicaCreator = new ClassReplicaCreator();
+ Class<?> replicaType = null;
+ if (isStatic || constructorArgs == null) {
+ replicaType = classReplicaCreator.createClassReplica(type);
+ } else {
+ try {
+ replicaType = classReplicaCreator.createInstanceReplica(constructorArgs.getConstructor().newInstance(
+ constructorArgs.getInitArgs()));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (InvocationTargetException e) {
+ Throwable targetException = e.getTargetException();
+ if (targetException instanceof RuntimeException) {
+ throw (RuntimeException) targetException;
+ }
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ }
+ return replicaType;
+ }
+
+ private static <T> T doCreateMock(Class<T> type, ConstructorArgs constructorArgs, final IMocksControl control,
+ Method... methods) {
+ T mock;
+ MocksControl mocksControl = ((MocksControl) control);
+ if (constructorArgs == null) {
+ if (methods == null) {
+ mock = mocksControl.createMock(type);
+ } else {
+ mock = mocksControl.createMock(null, type, null, methods);
+ }
+ } else {
+ if (methods == null) {
+ mock = mocksControl.createMock(null, type, constructorArgs);
+ } else {
+ mock = mocksControl.createMock(null, type, constructorArgs, methods);
+ }
+ }
+ return mock;
+ }
+
+ private static Set<Method> toSet(Method[] methods) {
+ return methods == null ? null : new HashSet<Method>(Arrays.asList(methods));
+ }
+
+ private static Class<?>[] mergeArgumentTypes(Class<?> firstArgumentType, Class<?>... additionalArgumentTypes) {
+ if (firstArgumentType == null) {
+ return additionalArgumentTypes == null ? new Class<?>[0] : additionalArgumentTypes;
+ } else if (additionalArgumentTypes == null) {
+ additionalArgumentTypes = new Class<?>[0];
+ }
+ final Class<?>[] argumentTypes = new Class[additionalArgumentTypes.length + 1];
+ argumentTypes[0] = firstArgumentType;
+ if (additionalArgumentTypes.length != 0) {
+ System.arraycopy(additionalArgumentTypes, 0, argumentTypes, 1, additionalArgumentTypes.length);
+ }
+ return argumentTypes;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> IExpectationSetters<T> doExpectPrivate(Object instance, Method methodToExpect,
+ Object... arguments) throws Exception {
+ WhiteboxImpl.performMethodInvocation(instance, methodToExpect, arguments);
+ return (IExpectationSetters<T>) org.easymock.EasyMock.expectLastCall();
+ }
+
+ private static synchronized void replay(Class<?>... types) {
+ for (Class<?> type : types) {
+ final MethodInvocationControl invocationHandler = MockRepository.getStaticMethodInvocationControl(type);
+ if (invocationHandler != null) {
+ invocationHandler.replay();
+ }
+
+ NewInvocationControl<?> newInvocationControl = MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ newInvocationControl.replay();
+ }
+ }
+ }
+
+ /**
+ * Note: doesn't clear PowerMock state.
+ */
+ private static synchronized void verifyClass(Class<?>... types) {
+ for (Class<?> type : types) {
+ final MethodInvocationControl invocationHandler = MockRepository.getStaticMethodInvocationControl(type);
+ if (invocationHandler != null) {
+ invocationHandler.verify();
+ }
+ NewInvocationControl<?> newInvocationControl = MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ try {
+ newInvocationControl.verify();
+ } catch (AssertionError e) {
+ NewInvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+ }
+ }
+ }
+
+ private static boolean isNiceReplayAndVerifyMode() {
+ final Boolean mode = (Boolean) MockRepository.getAdditionalState(NICE_REPLAY_AND_VERIFY_KEY);
+ return mode != null && mode;
+ }
+
+ /**
+ * Clears the state in LastControl that deals with MocksControl.
+ */
+ private static class EasyMockStateCleaner implements Runnable {
+
+ @Override
+ public void run() {
+ LastControl.reportLastControl(null);
+ clearStateFromOtherClassLoaders();
+ }
+
+ private void clearStateFromOtherClassLoaders() {
+ for (ClassLoader cl : classloadersToClear()) {
+ try {
+ final Class<?> lastControlClassByCL = Class.forName(LastControl.class.getName(), false, cl);
+ final Class<?> mocksControlClassByCL = Class.forName(MocksControl.class.getName(), false, cl);
+ final Method reportLastControl = lastControlClassByCL.getMethod("reportLastControl", mocksControlClassByCL);
+ reportLastControl.invoke(lastControlClassByCL, new Object[]{null});
+ } catch (Exception e) {
+ // Should never happen
+ throw new RuntimeException("Failed to clean up state", e);
+
+ }
+ }
+ }
+
+ private Iterable<ClassLoader> classloadersToClear() {
+ List<ClassLoader> loaders = new ArrayList<ClassLoader>();
+ final ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
+ final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (classFoundInClassloader(LastControl.class, systemClassLoader)) {
+ loaders.add(systemClassLoader);
+ }
+ if (classFoundInClassloader(LastControl.class, contextClassLoader)) {
+ loaders.add(contextClassLoader);
+ }
+ return loaders;
+ }
+
+ private boolean classFoundInClassloader(Class<?> cls, ClassLoader classLoader) {
+ try {
+ Class.forName(cls.getName(), false, classLoader);
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/annotation/Mock.java b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/Mock.java
new file mode 100644
index 0000000..b4a36e4
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/Mock.java
@@ -0,0 +1,80 @@
+package org.powermock.api.easymock.annotation;
+
+import org.powermock.core.classloader.annotations.PowerMockListener;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation can be placed on those fields in your test class that should
+ * be mocked. This eliminates the need to setup and tear-down mocks manually
+ * which minimizes repetitive test code and makes the test more readable. In
+ * order for PowerMock to control the life-cycle of the mocks you must supply
+ * the {@link PowerMockListener} annotation to the class-level of the test case.
+ * For example:
+ *
+ * <pre>
+ * ...
+ * @PowerMockListener(AnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @Mock
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ * Note that you can also create partial mocks by using the annotation. Let's
+ * say that the PersonService has a method called "getPerson" and another method
+ * called "savePerson" and these are the only two methods that you'd like to
+ * mock. Rewriting the previous example to accommodate this will give us the
+ * following test:
+ *
+ * <pre>
+ * ...
+ * @PowerMockListener(AnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @Mock({"getPerson", "savePerson"})
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ */
+
+ at Target( { ElementType.FIELD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface Mock {
+ String[] value() default "";
+
+ /**
+ * Name of the test subject field to which this mock will be assigned. Use to disambiguate the case where
+ * a mock may be assigned to multiple fields of the same type.
+ * When set, this mock will be assigned to the given field name in any test subject with a matching field name.
+ * If not set, injection is to all type-compatible fields in all test subjects.
+ * A given field name may only be used once, and there must be a matching field in at least one test subject.
+ *
+ * @return name of the field to inject to
+ **/
+ String fieldName() default "";
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockNice.java b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockNice.java
new file mode 100644
index 0000000..01a70ec
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockNice.java
@@ -0,0 +1,67 @@
+package org.powermock.api.easymock.annotation;
+
+import org.powermock.core.classloader.annotations.PowerMockListener;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation can be placed on those fields in your test class that should
+ * be mocked in a nice manner (i.e. by default allows all method calls and
+ * returns appropriate empty values (0, <code>null</code> or <code>false</code>
+ * )). This eliminates the need to setup and tear-down mocks manually which
+ * minimizes repetitive test code and makes the test more readable. In order for
+ * PowerMock to control the life-cycle of the mocks you must supply the
+ * {@link PowerMockListener} annotation to the class-level of the test case. For
+ * example when using the EasyMock API:
+ *
+ * <pre>
+ * @PowerMockListener(EasyMockAnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @MockNice
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ * Note that you can also create partial mocks by using the annotation. Let's
+ * say that the PersonService has a method called "getPerson" and another method
+ * called "savePerson" and these are the only two methods that you'd like to
+ * mock. Rewriting the previous example to accommodate this will give us the
+ * following test:
+ *
+ * <pre>
+ * @PowerMockListener(EasyMockAnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @MockNice({"getPerson", "savePerson"})
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ */
+
+ at Target( { ElementType.FIELD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface MockNice {
+ String[] value() default "";
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockStrict.java b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockStrict.java
new file mode 100644
index 0000000..ac7266b
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/annotation/MockStrict.java
@@ -0,0 +1,66 @@
+package org.powermock.api.easymock.annotation;
+
+import org.powermock.core.classloader.annotations.PowerMockListener;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation can be placed on those fields in your test class that should
+ * be mocked in a strict manner (i.e. the order of method calls are checked).
+ * This eliminates the need to setup and tear-down mocks manually which
+ * minimizes repetitive test code and makes the test more readable. In order for
+ * PowerMock to control the life-cycle of the mocks you must supply the
+ * {@link PowerMockListener} annotation to the class-level of the test case. For
+ * example when using the EasyMock API:
+ *
+ * <pre>
+ * @PowerMockListener(EasyMockAnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @MockStrict
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ * Note that you can also create partial mocks by using the annotation. Let's
+ * say that the PersonService has a method called "getPerson" and another method
+ * called "savePerson" and these are the only two methods that you'd like to
+ * mock. Rewriting the previous example to accommodate this will give us the
+ * following test:
+ *
+ * <pre>
+ * @PowerMockListener(EasyMockAnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @MockStrict({"getPerson", "savePerson"})
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ */
+
+ at Target( { ElementType.FIELD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface MockStrict {
+ String[] value() default "";
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/EasyMockMethodInvocationControl.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/EasyMockMethodInvocationControl.java
new file mode 100644
index 0000000..56aad8e
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/EasyMockMethodInvocationControl.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.internal.invocationcontrol;
+
+import org.easymock.MockType;
+import org.easymock.internal.MockInvocationHandler;
+import org.easymock.internal.MocksControl;
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * The default implementation of the {@link MethodInvocationControl} interface.
+ */
+public class EasyMockMethodInvocationControl<T> implements MethodInvocationControl {
+
+ private MockInvocationHandler invocationHandler;
+
+ private Set<Method> mockedMethods;
+
+ private T mockInstance;
+
+ private boolean hasReplayed;
+ private boolean hasVerified;
+
+ /**
+ * Initializes internal state.
+ *
+ * @param invocationHandler The mock invocation handler to be associated with this
+ * instance.
+ * @param methodsToMock The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null all methods for the
+ * <code>invocationHandler</code> are considered to be mocked.
+ * @param mockInstance The actual mock instance. May be <code>null</code>. Even
+ * though the mock instance may not be used it's needed to keep a
+ * reference to this object otherwise it may be garbage collected
+ * in some situations. For example when mocking static methods we
+ * don't return the mock object and thus it will be garbage
+ * collected (and thus the finalize method will be invoked which
+ * will be caught by the proxy and the test will fail because we
+ * haven't setup expectations for this method) because then that
+ * object has no reference. In order to avoid this we keep a
+ * reference to this instance here.
+ */
+ public EasyMockMethodInvocationControl(MockInvocationHandler invocationHandler, Set<Method> methodsToMock, T mockInstance) {
+ if (invocationHandler == null) {
+ throw new IllegalArgumentException("Invocation Handler cannot be null.");
+ }
+
+ this.invocationHandler = invocationHandler;
+ this.mockedMethods = methodsToMock;
+ this.mockInstance = mockInstance;
+ }
+
+ /**
+ * Initializes internal state.
+ *
+ * @param invocationHandler The mock invocation handler to be associated with this
+ * instance.
+ * @param methodsToMock The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null all methods for the
+ * <code>invocationHandler</code> are considered to be mocked.
+ */
+ public EasyMockMethodInvocationControl(MockInvocationHandler invocationHandler, Set<Method> methodsToMock) {
+ this(invocationHandler, methodsToMock, null);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isMocked(Method method) {
+ return mockedMethods == null || (mockedMethods != null && mockedMethods.contains(method));
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] arguments) throws Throwable {
+ return invocationHandler.invoke(mockInstance == null ? proxy : mockInstance, method, arguments);
+ }
+
+ public MocksControl.MockType getMockType() {
+ final MocksControl control = invocationHandler.getControl();
+ if (WhiteboxImpl.getFieldsOfType(control, MocksControl.MockType.class).isEmpty()) {
+ // EasyMock is of version 3.2+
+ final MockType mockType = WhiteboxImpl.getInternalState(control, MockType.class);
+ switch (mockType) {
+ case DEFAULT:
+ return MocksControl.MockType.DEFAULT;
+ case NICE:
+ return MocksControl.MockType.NICE;
+ case STRICT:
+ return MocksControl.MockType.STRICT;
+ default:
+ throw new IllegalStateException("PowerMock doesn't seem to work with the used EasyMock version. Please report to the PowerMock mailing list");
+ }
+ } else {
+ return WhiteboxImpl.getInternalState(control, MocksControl.MockType.class);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object replay(Object... mocks) {
+ // Silently ignore replay if someone has replayed the mock before.
+ if (!hasReplayed) {
+ invocationHandler.getControl().replay();
+ hasReplayed = true;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object verify(Object... mocks) {
+ // Silently ignore verify if someone has verified the mock before.
+ if (!hasVerified) {
+ invocationHandler.getControl().verify();
+ hasVerified = true;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object reset(Object... mocks) {
+ invocationHandler.getControl().reset();
+ hasReplayed = false;
+ hasVerified = false;
+ return null;
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlAssertionError.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlAssertionError.java
new file mode 100644
index 0000000..9a1ab5c
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlAssertionError.java
@@ -0,0 +1,23 @@
+package org.powermock.api.easymock.internal.invocationcontrol;
+
+import org.powermock.core.spi.support.InvocationSubstitute;
+
+import java.util.regex.Matcher;
+
+public class NewInvocationControlAssertionError {
+ public static void throwAssertionErrorForNewSubstitutionFailure(AssertionError oldError, Class<?> type) {
+ /*
+ * We failed to verify the new substitution mock. This happens when, for
+ * example, the user has done something like
+ * expectNew(MyClass.class).andReturn(myMock).times(3) when in fact an
+ * instance of MyClass has been created less or more times than 3.
+ */
+ String message = oldError.getMessage();
+ final String newSubsitutionMethodName = InvocationSubstitute.class.getDeclaredMethods()[0].getName();
+ final String className = InvocationSubstitute.class.getSimpleName();
+ message = message.replaceAll(className+"."+newSubsitutionMethodName, Matcher.quoteReplacement(type.getName()));
+ message = message.replaceAll("method", "constructor");
+
+ throw new AssertionError(message);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlImpl.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlImpl.java
new file mode 100644
index 0000000..1614e5c
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/invocationcontrol/NewInvocationControlImpl.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.internal.invocationcontrol;
+
+import org.easymock.EasyMock;
+import org.easymock.IExpectationSetters;
+import org.easymock.internal.MocksControl;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Constructor;
+
+public class NewInvocationControlImpl<T> implements NewInvocationControl<IExpectationSetters<T>> {
+ private final InvocationSubstitute<T> substitute;
+ private final Class<T> subsitutionType;
+ private boolean hasReplayed;
+ private boolean hasVerified;
+
+ public NewInvocationControlImpl(InvocationSubstitute<T> substitute, Class<T> type) {
+ if (substitute == null) {
+ throw new IllegalArgumentException("Internal error: substitute cannot be null.");
+ }
+ this.subsitutionType = type;
+ this.substitute = substitute;
+ }
+
+ @Override
+ public Object invoke(Class<?> type, Object[] args, Class<?>[] sig) throws Exception {
+ Constructor<?> constructor = WhiteboxImpl.getConstructor(type, sig);
+ if (constructor.isVarArgs()) {
+ /*
+ * Get the last argument because this contains the actual varargs
+ * arguments.
+ */
+ int length = constructor.getParameterTypes().length;
+ args = (Object[]) args[length-1];
+ }
+ try {
+ final MocksControl.MockType mockType = ((EasyMockMethodInvocationControl<?>) MockRepository.getInstanceMethodInvocationControl(substitute))
+ .getMockType();
+ Object result = substitute.performSubstitutionLogic(args);
+
+ if (result == null) {
+ if (mockType == MocksControl.MockType.NICE) {
+ result = EasyMock.createNiceMock(subsitutionType);
+ } else {
+ throw new IllegalStateException("Must replay class " + type.getName() + " to get configured expectation.");
+ }
+ }
+ return result;
+ } catch (AssertionError e) {
+ NewInvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+
+ // Won't happen
+ return null;
+ }
+
+ @Override
+ public IExpectationSetters<T> expectSubstitutionLogic(Object... arguments) throws Exception {
+ return EasyMock.expect(substitute.performSubstitutionLogic(arguments));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object replay(Object... mocks) {
+ if (!hasReplayed) {
+ EasyMock.replay(substitute);
+ hasReplayed = true;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object verify(Object... mocks) {
+ if (!hasVerified) {
+ EasyMock.verify(substitute);
+ hasVerified = true;
+ }
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object reset(Object... mocks) {
+ EasyMock.reset(substitute);
+ hasReplayed = false;
+ hasVerified = false;
+ return null;
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/MockStrategy.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/MockStrategy.java
new file mode 100644
index 0000000..f173c45
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/MockStrategy.java
@@ -0,0 +1,9 @@
+package org.powermock.api.easymock.internal.mockstrategy;
+
+import org.easymock.IMocksControl;
+
+public interface MockStrategy {
+
+ IMocksControl createMockControl(Class<?> type);
+
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/AbstractMockStrategyBase.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/AbstractMockStrategyBase.java
new file mode 100644
index 0000000..3a3b02c
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/AbstractMockStrategyBase.java
@@ -0,0 +1,27 @@
+package org.powermock.api.easymock.internal.mockstrategy.impl;
+
+import org.easymock.IMocksControl;
+import org.easymock.internal.MocksControl;
+import org.easymock.internal.MocksControl.MockType;
+import org.powermock.api.easymock.internal.mockstrategy.MockStrategy;
+
+/**
+ * Base class that should be used by all mock strategies. Enables mocking of
+ * signed classes.
+ */
+public abstract class AbstractMockStrategyBase implements MockStrategy {
+
+ private final MockType mockType;
+
+ public AbstractMockStrategyBase(MockType mockType) {
+ if (mockType == null) {
+ throw new IllegalArgumentException("Internal error: mockType cannot be null");
+ }
+ this.mockType = mockType;
+ }
+
+ @Override
+ public IMocksControl createMockControl(Class<?> type) {
+ return new MocksControl(mockType);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/DefaultMockStrategy.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/DefaultMockStrategy.java
new file mode 100644
index 0000000..c5899b3
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/DefaultMockStrategy.java
@@ -0,0 +1,10 @@
+package org.powermock.api.easymock.internal.mockstrategy.impl;
+
+import org.easymock.internal.MocksControl.MockType;
+
+public class DefaultMockStrategy extends AbstractMockStrategyBase {
+
+ public DefaultMockStrategy() {
+ super(MockType.DEFAULT);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/NiceMockStrategy.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/NiceMockStrategy.java
new file mode 100644
index 0000000..1b0b9a7
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/NiceMockStrategy.java
@@ -0,0 +1,10 @@
+package org.powermock.api.easymock.internal.mockstrategy.impl;
+
+import org.easymock.internal.MocksControl.MockType;
+
+public class NiceMockStrategy extends AbstractMockStrategyBase {
+
+ public NiceMockStrategy() {
+ super(MockType.NICE);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/StrictMockStrategy.java b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/StrictMockStrategy.java
new file mode 100644
index 0000000..4c7e14d
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/internal/mockstrategy/impl/StrictMockStrategy.java
@@ -0,0 +1,10 @@
+package org.powermock.api.easymock.internal.mockstrategy.impl;
+
+import org.easymock.internal.MocksControl.MockType;
+
+public class StrictMockStrategy extends AbstractMockStrategyBase {
+
+ public StrictMockStrategy() {
+ super(MockType.STRICT);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/AbstractEasyMockLogPolicyBase.java b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/AbstractEasyMockLogPolicyBase.java
new file mode 100644
index 0000000..e57826d
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/AbstractEasyMockLogPolicyBase.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.mockpolicies;
+
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.mockpolicies.support.LogPolicySupport;
+
+import java.lang.reflect.Method;
+
+import static org.easymock.EasyMock.makeThreadSafe;
+import static org.powermock.api.easymock.PowerMock.createNiceMock;
+
+/**
+ * A base class for EasyMock log policies.
+ */
+abstract class AbstractEasyMockLogPolicyBase implements PowerMockPolicy {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(getFullyQualifiedNamesOfClassesToLoadByMockClassloader());
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ LogPolicySupport support = new LogPolicySupport();
+
+ Method[] loggerFactoryMethods = support.getLoggerMethods(getLoggerFactoryClassName(), getLoggerMethodName(), getLogFrameworkName());
+
+ Class<?> loggerType = null;
+ try {
+ loggerType = support.getType(getLoggerClassToMock(), getLogFrameworkName());
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ final Object loggerMock = createNiceMock(loggerType);
+ // Allow the mock to be used in a multi-threaded environment
+ makeThreadSafe(loggerMock, true);
+
+ for (Method method : loggerFactoryMethods) {
+ settings.stubMethod(method, loggerMock);
+ }
+ }
+
+ /**
+ * @return The name of the methods in the Logger Factory that should return
+ * a mock upon invocation.
+ */
+ protected abstract String getLoggerMethodName();
+
+ /**
+ * @return The fully-qualified class name of the Logger Factory that
+ * contains the methods that should return a mock upon invocation.
+ */
+ protected abstract String getLoggerFactoryClassName();
+
+ /**
+ * @return The fully-qualified class name of the class that should be
+ * mocked. The mock instance of this class will then be returned
+ * each time a specified method in the Logger Factory is invoked.
+ */
+ protected abstract String getLoggerClassToMock();
+
+ /**
+ * @return The name of the log framework. Used in error messages, for
+ * example if the {@link #getLoggerFactoryClassName()} cannot be
+ * found in the classpath.
+ */
+ protected abstract String getLogFrameworkName();
+
+ /**
+ * @return The fully-qualified names of the classes that should be loaded by
+ * the mock classloader.
+ */
+ protected abstract String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader();
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/JclMockPolicy.java b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/JclMockPolicy.java
new file mode 100644
index 0000000..922c076
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/JclMockPolicy.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.mockpolicies;
+
+
+/**
+ * A Jakarta Commons-Logging (JCL) mock policy. This mock policy deals with
+ * solving JCL related mocking issues. It takes care of loading all concerned
+ * JCL classes through the correct class-loader and automatically prepares and
+ * injects logger instances. This policy does the following:
+ * <ol>
+ * <li>Prepares all classes in the <tt>org.apache.commons.logging</tt> for test
+ * as well as <tt>org.apache.log4j.Appender</tt> and
+ * <tt>org.apache.log4j.xml.DOMConfigurator</tt>.</li>
+ * <li>All calls to the
+ * <tt>org.apache.commons.logging.LogFactory#getLog(..)</tt> methods are
+ * intercepted and returns a nice mock of type
+ * <tt>org.apache.commons.logging.Log</tt>.</li>
+ * </ol>
+ */
+public class JclMockPolicy extends AbstractEasyMockLogPolicyBase {
+
+ /**
+ * Loads all log4j classes with the mock classloader.
+ */
+ protected String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader() {
+ return new String[] { "org.apache.commons.logging.*", "org.apache.log4j.Appender", "org.apache.log4j.xml.DOMConfigurator" };
+ }
+
+ @Override
+ protected String getLogFrameworkName() {
+ return "commons-logging";
+ }
+
+ @Override
+ protected String getLoggerClassToMock() {
+ return "org.apache.commons.logging.Log";
+ }
+
+ @Override
+ protected String getLoggerFactoryClassName() {
+ return "org.apache.commons.logging.LogFactory";
+ }
+
+ @Override
+ protected String getLoggerMethodName() {
+ return "getLog";
+ }
+}
\ No newline at end of file
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Log4jMockPolicy.java b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Log4jMockPolicy.java
new file mode 100644
index 0000000..f5d85f4
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Log4jMockPolicy.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.mockpolicies;
+
+
+/**
+ * A log4j mock policy. This mock policy deals with solving log4j related
+ * mocking issues. It takes care of loading all concerned log4j classes through
+ * the correct class-loader and automatically prepares and injects logger
+ * instances. This policy does the following:
+ * <ol>
+ * <li>Prepares all log4j classes and interfaces for testing.</li>
+ * <li>All calls to the <tt>org.apache.log4j.Logger#getLogger(..)</tt> methods
+ * are intercepted and returns a nice mock of type
+ * <tt>org.apache.log4j.Logger</tt>.</li>
+ * </ol>
+ */
+public class Log4jMockPolicy extends AbstractEasyMockLogPolicyBase {
+
+ private static final String LOGGER_CLASS = "org.apache.log4j.Logger";
+
+ /**
+ * Loads all log4j classes with the mock classloader.
+ */
+ @Override
+ protected String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader() {
+ return new String[] { "org.apache.log4j.*" };
+ }
+
+ @Override
+ protected String getLogFrameworkName() {
+ return "log4j";
+ }
+
+ @Override
+ protected String getLoggerClassToMock() {
+ return LOGGER_CLASS;
+ }
+
+ @Override
+ protected String getLoggerFactoryClassName() {
+ return LOGGER_CLASS;
+ }
+
+ @Override
+ protected String getLoggerMethodName() {
+ return "getLogger";
+ }
+}
\ No newline at end of file
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Slf4jMockPolicy.java b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Slf4jMockPolicy.java
new file mode 100644
index 0000000..b16cddb
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/mockpolicies/Slf4jMockPolicy.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.mockpolicies;
+
+
+/**
+ * An slf4j mock policy. This mock policy deals with solving slf4j related
+ * mocking issues. It takes care of loading all concerned slf4j and log4j
+ * classes through the correct class-loader and automatically prepares and
+ * injects logger instances. This policy does the following:
+ * <ol>
+ * <li>Prepares <tt>org.apache.log4j.Appender</tt>,
+ * <tt>org.slf4j.LoggerFactory</tt> and
+ * <tt>org.apache.log4j.xml.DOMConfigurator</tt> for testing.</li>
+ * <li>All calls to the <tt>org.slf4j.LoggerFactory#getLogger(..)</tt> methods
+ * are intercepted and returns a nice mock of type <tt>org.slf4j.Logger</tt>.</li>
+ * </ol>
+ */
+public class Slf4jMockPolicy extends AbstractEasyMockLogPolicyBase {
+
+ @Override
+ protected String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader() {
+ return new String[] { "org.apache.log4j.Appender", "org.slf4j.LoggerFactory", "org.apache.log4j.xml.DOMConfigurator" };
+ }
+
+ @Override
+ protected String getLogFrameworkName() {
+ return "slf4j";
+ }
+
+ @Override
+ protected String getLoggerClassToMock() {
+ return "org.slf4j.Logger";
+ }
+
+ @Override
+ protected String getLoggerFactoryClassName() {
+ return "org.slf4j.LoggerFactory";
+ }
+
+ @Override
+ protected String getLoggerMethodName() {
+ return "getLogger";
+ }
+}
\ No newline at end of file
diff --git a/api/easymock/src/main/java/org/powermock/api/easymock/powermocklistener/AnnotationEnabler.java b/api/easymock/src/main/java/org/powermock/api/easymock/powermocklistener/AnnotationEnabler.java
new file mode 100644
index 0000000..71eea91
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/easymock/powermocklistener/AnnotationEnabler.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.easymock.powermocklistener;
+
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.api.easymock.annotation.MockStrict;
+import org.powermock.core.classloader.annotations.Mock;
+
+/**
+ * Before each test method all fields annotated with {@link Mock},
+ * {@link MockNice} or {@link MockStrict} will have mock objects created for
+ * them and injected to the fields.
+ *
+ * @deprecated Test Runners uses an annotation enabling listener per default
+ * since version 1.3. You should just remove this listener.
+ */
+public class AnnotationEnabler extends org.powermock.api.extension.listener.AnnotationEnabler {
+
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java b/api/easymock/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java
new file mode 100644
index 0000000..472df7d
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.agent;
+
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.core.agent.JavaAgentFrameworkRegister;
+
+/**
+ * Implementation of JavaAgentFrameworkRegister for EasyMock framework.
+ */
+public class JavaAgentFrameworkRegisterImpl implements JavaAgentFrameworkRegister {
+ @Override
+ public void set(JavaAgentClassRegister javaAgentClassRegister) {
+
+ }
+
+ @Override
+ public void clear() {
+
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
new file mode 100644
index 0000000..474cff0
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.extension.listener;
+
+import org.powermock.api.easymock.EasyMockConfiguration;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.api.easymock.annotation.MockStrict;
+import org.powermock.core.classloader.annotations.Mock;
+import org.powermock.core.spi.listener.AnnotationEnablerListener;
+import org.powermock.core.spi.support.AbstractPowerMockTestListenerBase;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * <p>
+ * Before each test method all fields annotated with
+ * {@link Mock}, {@link org.powermock.api.easymock.annotation.Mock}, {@link org.easymock.Mock}
+ * {@link MockNice} or {@link MockStrict} will have mock objects created for
+ * them and injected to the fields.
+ * </p>
+ * <p>
+ * Also all fields annotated with {@link org.easymock.TestSubject} will be processed and mocks are injected to fields
+ * object, if these fields not null.
+ * </p>
+ * <p>
+ * It will only inject to fields that haven't been set before (i.e that are
+ * <code>null</code>).
+ * </p>
+ *
+ * @see org.powermock.api.easymock.annotation.Mock
+ * @see org.easymock.Mock
+ * @see org.easymock.TestSubject
+ *
+ */
+ at SuppressWarnings("deprecation")
+public class AnnotationEnabler extends AbstractPowerMockTestListenerBase implements AnnotationEnablerListener {
+
+
+ @SuppressWarnings("unchecked")
+ public Class<? extends Annotation>[] getMockAnnotations() {
+ return new Class[]{org.powermock.api.easymock.annotation.Mock.class, Mock.class, MockNice.class, MockStrict.class};
+ }
+
+ @Override
+ public void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception {
+
+ EasyMockConfiguration easyMockConfiguration = EasyMockConfiguration.getConfiguration();
+
+ if (!easyMockConfiguration.isReallyEasyMock()) {
+ // Easymock API could be used as depends for JMock.
+ return;
+ }
+
+ // first emulate default EasyMockRunner behavior
+ if (easyMockConfiguration.isInjectMocksSupported()) {
+ Whitebox.invokeMethod(Class.forName("org.easymock.EasyMockSupport"), "injectMocks", testInstance);
+ }
+
+ // then inject in empty fields mock created via PowerMock
+
+ getEasyMockAnnotationSupport(testInstance).injectMocks();
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ protected EasyMockAnnotationSupport getEasyMockAnnotationSupport(Object testInstance) {
+ return new EasyMockAnnotationSupport(testInstance);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationGlobalMetadata.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationGlobalMetadata.java
new file mode 100644
index 0000000..38b09dc
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationGlobalMetadata.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ *
+ */
+class AnnotationGlobalMetadata {
+
+ private final List<AnnotationMockMetadata> qualifiedInjections = new ArrayList<AnnotationMockMetadata>(5);
+
+ private final List<AnnotationMockMetadata> unqualifiedInjections = new ArrayList<AnnotationMockMetadata>(5);
+
+ private final Set<String> qualifiers = new HashSet<String>();
+
+ public List<AnnotationMockMetadata> getQualifiedInjections() {
+ return qualifiedInjections;
+ }
+
+ public List<AnnotationMockMetadata> getUnqualifiedInjections() {
+ return unqualifiedInjections;
+ }
+
+ public void add(List<AnnotationMockMetadata> mocksMetadata) {
+ for (AnnotationMockMetadata mockMetadata : mocksMetadata) {
+ add(mockMetadata);
+ }
+ }
+
+ private void add(AnnotationMockMetadata mockMetadata) {
+
+ String qualifier = mockMetadata.getQualifier();
+
+ if (qualifier.length() != 0) {
+ blockDuplicateQualifiers(qualifier);
+ qualifiedInjections.add(mockMetadata);
+ } else {
+ unqualifiedInjections.add(mockMetadata);
+ }
+ }
+
+ private void blockDuplicateQualifiers(String qualifier) {
+ if (!qualifiers.add(qualifier)) {
+ throw new RuntimeException(String.format("At least two mocks have fieldName qualifier '%s'", qualifier));
+ }
+ }
+
+
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreator.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreator.java
new file mode 100644
index 0000000..e023dd6
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreator.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import java.lang.reflect.Method;
+
+/**
+ *
+ */
+interface AnnotationMockCreator {
+ Object createMockInstance(final Class<?> type, final Method[] methods);
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreatorFactory.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreatorFactory.java
new file mode 100644
index 0000000..7a4fd3b
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockCreatorFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import java.lang.reflect.Method;
+
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.createNiceMock;
+import static org.powermock.api.easymock.PowerMock.createStrictMock;
+
+/**
+ *
+ */
+class AnnotationMockCreatorFactory {
+ public AnnotationMockCreator createDefaultMockCreator() {
+ return new AnnotationMockCreator() {
+ @Override
+ public Object createMockInstance(Class<?> type, Method[] methods) {
+ return createMock(type, methods);
+ }
+ };
+ }
+
+ public AnnotationMockCreator createNiceMockCreator() {
+ return new AnnotationMockCreator() {
+ @Override
+ public Object createMockInstance(Class<?> type, Method[] methods) {
+ return createNiceMock(type, methods);
+ }
+ };
+ }
+
+ public AnnotationMockCreator createStrictMockCreator() {
+ return new AnnotationMockCreator() {
+ @Override
+ public Object createMockInstance(Class<?> type, Method[] methods) {
+ return createStrictMock(type, methods);
+ }
+ };
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockMetadata.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockMetadata.java
new file mode 100644
index 0000000..add91d4
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockMetadata.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+
+ at SuppressWarnings("WeakerAccess")
+public class AnnotationMockMetadata {
+ private final Class<?> type;
+ private final Method[] methods;
+ private final String qualifier;
+ private final Class<? extends Annotation> annotation;
+ private final Annotation annotationInstance;
+ private Object mock;
+
+ public AnnotationMockMetadata(Class<? extends Annotation> annotation, Field field) throws
+ Exception {
+ this.annotation = annotation;
+ this.annotationInstance = field.getAnnotation(annotation);
+ this.type = field.getType();
+ this.methods = getMethod();
+ this.qualifier = findQualifier();
+ }
+
+ private String findQualifier() {
+ String fieldName = "";
+ try {
+ fieldName = Whitebox.invokeMethod(annotationInstance, "fieldName");
+ } catch (Exception e) {
+ // do nothing, because it means that Mock annotation doesn't support qualifier. S
+ // ee org.easymock.Mock.fieldName
+ }
+
+ if (fieldName.length() == 0) {
+ return "";
+ } else {
+ return fieldName;
+ }
+ }
+
+ public String getQualifier() {
+ return qualifier;
+ }
+
+ public Class<? extends Annotation> getAnnotation() {
+ return annotation;
+ }
+
+ public Class<?> getType() {
+ return type;
+ }
+
+ public Method[] getMethods() {
+ return methods;
+ }
+
+ private Method[] getMethod() throws Exception {
+
+ final String[] value = Whitebox.invokeMethod(annotationInstance, "value");
+ if (value.length != 1 || !"".equals(value[0])) {
+ return Whitebox.getMethods(type, value);
+ }
+ return null;
+ }
+
+ public Object getMock() {
+ return mock;
+ }
+
+ public void setMock(Object mock) {
+ this.mock = mock;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+
+ AnnotationMockMetadata that = (AnnotationMockMetadata) o;
+
+ if (type != null ? !type.equals(that.type) : that.type != null) { return false; }
+ // Probably incorrect - comparing Object[] arrays with Arrays.equals
+ return Arrays.equals(methods, that.methods) && (qualifier != null ? qualifier.equals(that.qualifier) : that.qualifier == null);
+
+ }
+
+ @Override
+ public int hashCode() {
+ int result = type != null ? type.hashCode() : 0;
+ result = 31 * result + Arrays.hashCode(methods);
+ result = 31 * result + (qualifier != null ? qualifier.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockScanner.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockScanner.java
new file mode 100644
index 0000000..90d3077
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/AnnotationMockScanner.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+class AnnotationMockScanner {
+ private final Class<? extends Annotation> annotation;
+
+ public AnnotationMockScanner(Class<? extends Annotation> annotation) {
+ this.annotation = annotation;
+ }
+
+ public List<AnnotationMockMetadata> scan(Object instance) throws Exception {
+ final List<AnnotationMockMetadata> mocksMetadata = new ArrayList<AnnotationMockMetadata>();
+ final Set<Field> fields = getFields(instance);
+ for (Field field : fields) {
+ if (field.get(instance) != null) {
+ continue;
+ }
+ mocksMetadata.add(new AnnotationMockMetadata(annotation, field));
+ }
+ return mocksMetadata;
+ }
+
+ @SuppressWarnings("unchecked")
+ private Set<Field> getFields(Object instance) {
+ final Set<Field> fields;
+ if (annotation != null) {
+ fields = Whitebox.getFieldsAnnotatedWith(instance, annotation);
+ }else{
+ fields = Whitebox.getAllInstanceFields(instance);
+ }
+ return fields;
+ }
+
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/EasyMockAnnotationSupport.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/EasyMockAnnotationSupport.java
new file mode 100644
index 0000000..6acde42
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/EasyMockAnnotationSupport.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import org.powermock.api.easymock.EasyMockConfiguration;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.api.easymock.annotation.MockStrict;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class works like as {@link org.easymock.EasyMockSupport} and is used to create and inject mocks to
+ * annotated fields of an instance of test class.
+ * @see Mock
+ * @see org.easymock.Mock
+ * @see org.easymock.TestSubject
+ */
+ at SuppressWarnings("WeakerAccess")
+public class EasyMockAnnotationSupport {
+
+ private final Object testInstance;
+ private final AnnotationMockCreatorFactory annotationMockCreatorFactory;
+ private final AnnotationGlobalMetadata globalMetadata;
+ private final EasyMockConfiguration easyMockConfiguration;
+
+ public EasyMockAnnotationSupport(Object testInstance) {
+ this.testInstance = testInstance;
+ this.annotationMockCreatorFactory = new AnnotationMockCreatorFactory();
+ this.globalMetadata = new AnnotationGlobalMetadata();
+ this.easyMockConfiguration = EasyMockConfiguration.getConfiguration();
+ }
+
+ public void injectMocks() throws Exception {
+ injectStrictMocks();
+ injectNiceMocks();
+ injectDefaultMocks();
+ injectTestSubjectMocks();
+ }
+
+ protected void injectStrictMocks() throws Exception {
+ inject(testInstance, MockStrict.class, annotationMockCreatorFactory.createStrictMockCreator());
+ }
+
+ protected void injectNiceMocks() throws Exception {
+ inject(testInstance, MockNice.class, annotationMockCreatorFactory.createNiceMockCreator());
+ }
+
+ @SuppressWarnings("deprecation")
+ protected void injectDefaultMocks() throws Exception {
+ inject(testInstance, Mock.class, annotationMockCreatorFactory.createDefaultMockCreator());
+ inject(testInstance, org.powermock.core.classloader.annotations.Mock.class, annotationMockCreatorFactory.createDefaultMockCreator());
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void injectTestSubjectMocks() throws IllegalAccessException {
+ if (easyMockConfiguration.isTestSubjectSupported()) {
+ TestSubjectInjector testSubjectInjector = new TestSubjectInjector(testInstance, globalMetadata);
+ testSubjectInjector.injectTestSubjectMocks();
+ }
+ }
+
+
+ protected void inject(Object injectCandidateInstance, Class<? extends Annotation> annotation, AnnotationMockCreator mockCreator) throws Exception {
+
+ AnnotationMockScanner scanner = new AnnotationMockScanner(annotation);
+
+ List<AnnotationMockMetadata> mocksMetadata = scanner.scan(injectCandidateInstance);
+ globalMetadata.add(mocksMetadata);
+
+ for (AnnotationMockMetadata mockMetadata : mocksMetadata) {
+ injectMock(injectCandidateInstance, mockMetadata, mockCreator, new AnnotationInjectFieldSearcher());
+ }
+
+
+ }
+
+ protected void injectMock(Object injectCandidateInstance, AnnotationMockMetadata mockMetadata,
+ AnnotationMockCreator mockCreator, InjectFieldSearcher fieldSearch) throws IllegalAccessException {
+ Object mock = createMock(mockCreator, mockMetadata);
+ Field field = fieldSearch.findField(injectCandidateInstance, mockMetadata);
+ if (field != null && mock != null) {
+ field.setAccessible(true);
+ field.set(injectCandidateInstance, mock);
+ }
+ }
+
+
+ protected Object createMock(AnnotationMockCreator mockCreator, AnnotationMockMetadata mockMetadata) {
+ if (mockMetadata.getMock() == null) {
+ Object mock = mockCreator.createMockInstance(mockMetadata.getType(), mockMetadata.getMethods());
+ mockMetadata.setMock(mock);
+ }
+ return mockMetadata.getMock();
+ }
+
+
+ protected interface InjectFieldSearcher {
+ Field findField(Object instance, AnnotationMockMetadata mockMetadata);
+ }
+
+
+ @SuppressWarnings("unchecked")
+ protected static class AnnotationInjectFieldSearcher implements InjectFieldSearcher {
+
+ @Override
+ public Field findField(Object instance, AnnotationMockMetadata mockMetadata) {
+ Set<Field> candidates = Whitebox.getFieldsAnnotatedWith(instance, mockMetadata.getAnnotation());
+ if (candidates.size() == 1) {
+ return candidates.iterator().next();
+ }
+ return null;
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/listener/TestSubjectInjector.java b/api/easymock/src/main/java/org/powermock/api/extension/listener/TestSubjectInjector.java
new file mode 100644
index 0000000..28cbad7
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/listener/TestSubjectInjector.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.listener;
+
+import org.easymock.Mock;
+import org.easymock.TestSubject;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Field;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The class injects mocks created with {@link Mock}, {@link org.powermock.api.easymock.annotation.Mock}
+ * and {@link org.powermock.core.classloader.annotations.Mock} to fields of objects which is annotated with {@link TestSubject}
+ * @see TestSubject
+ * @since 1.6.5
+ */
+ at SuppressWarnings({"deprecation", "WeakerAccess"})
+class TestSubjectInjector {
+
+ private final Object testInstance;
+ private final AnnotationGlobalMetadata globalMetadata;
+
+ public TestSubjectInjector(Object testInstance, AnnotationGlobalMetadata globalMetadata) {
+
+ this.testInstance = testInstance;
+ this.globalMetadata = globalMetadata;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void injectTestSubjectMocks() throws IllegalAccessException {
+
+ Set<Field> testSubjectFields = Whitebox.getFieldsAnnotatedWith(testInstance, TestSubject.class);
+ for (Field testSubjectField : testSubjectFields) {
+ Object testSubject = testSubjectField.get(testInstance);
+ if (testSubject == null) {
+ throw new NullPointerException("Have you forgotten to instantiate " + testSubjectField.getName() + "?");
+ }
+ injectTestSubjectFields(testSubject);
+
+ }
+ }
+
+ protected void injectTestSubjectFields(Object testSubject) throws IllegalAccessException {
+ Set<Field> targetFields = new HashSet<Field>(Whitebox.getAllInstanceFields(testSubject));
+ targetFields = injectByName(targetFields, testSubject);
+ injectByType(targetFields, testSubject);
+ }
+
+ void injectByType(Set<Field> targetFields, Object testSubject) throws IllegalAccessException {
+ for (Field targetField : targetFields) {
+
+ InjectionTarget target = new InjectionTarget(targetField);
+
+ AnnotationMockMetadata toAssign = findUniqueAssignable(target);
+
+ if (toAssign == null) {
+ continue;
+ }
+
+ target.inject(testSubject, toAssign);
+ }
+ }
+
+ AnnotationMockMetadata findUniqueAssignable(InjectionTarget target) {
+ AnnotationMockMetadata toAssign = null;
+ for (AnnotationMockMetadata mockMetadata : globalMetadata.getUnqualifiedInjections()) {
+ if (target.accepts(mockMetadata)) {
+ if (toAssign != null) {
+ throw new RuntimeException(String.format("At least two mocks can be assigned to '%s': %s and %s", target.getField(), toAssign.getMock(), mockMetadata.getMock()));
+ }
+ toAssign = mockMetadata;
+ }
+ }
+ return toAssign;
+ }
+
+ Set<Field> injectByName(Set<Field> targetFields, Object targetObject) throws IllegalAccessException {
+ Class<?> targetClass = targetObject.getClass();
+
+ for (AnnotationMockMetadata mockMetadata : globalMetadata.getQualifiedInjections()) {
+ Field targetField = getFieldByName(targetClass, mockMetadata.getQualifier());
+
+ if (targetField == null) {
+ continue;
+ }
+
+ InjectionTarget target = new InjectionTarget(targetField);
+
+ if (target.accepts(mockMetadata)) {
+ target.inject(targetObject, mockMetadata);
+ targetFields.remove(targetField);
+ }
+ }
+
+ return targetFields;
+ }
+
+ private Field getFieldByName(Class<?> clazz, String fieldName) {
+ try {
+ return clazz.getDeclaredField(fieldName);
+ } catch (NoSuchFieldException e) {
+ return null;
+ } catch (SecurityException e) {
+ return null;
+ }
+ }
+
+ private static class InjectionTarget {
+
+ private final Field field;
+
+ public InjectionTarget(Field field) {
+
+ this.field = field;
+ }
+
+ public Field getField() {
+ return field;
+ }
+
+ public boolean accepts(AnnotationMockMetadata mockMetadata) {
+ return field.getType().isAssignableFrom(mockMetadata.getType());
+ }
+
+ public void inject(Object targetObject, AnnotationMockMetadata mockMetadata) throws IllegalAccessException {
+ field.setAccessible(true);
+
+ Object value = field.get(targetObject);
+
+ if (value == null) {
+ field.set(targetObject, mockMetadata.getMock());
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java b/api/easymock/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
new file mode 100644
index 0000000..8eac610
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
@@ -0,0 +1,33 @@
+package org.powermock.api.extension.proxyframework;
+
+import net.sf.cglib.proxy.Enhancer;
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ * CGLib proxy framework setup.
+ */
+public class ProxyFrameworkImpl implements ProxyFramework {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Class<?> getUnproxiedType(Class<?> type) {
+ Class<?> currentType = type;
+ while (isProxy(currentType)) {
+ currentType = currentType.getSuperclass();
+ }
+ return currentType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isProxy(Class<?> type) {
+ if (type == null) {
+ return false;
+ }
+ return type.getName().contains("$$EnhancerByCGLIB$$") || Enhancer.isEnhanced(type);
+ }
+}
diff --git a/api/easymock/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java b/api/easymock/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
new file mode 100644
index 0000000..89054a3
--- /dev/null
+++ b/api/easymock/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.reporter;
+
+import org.powermock.core.reporter.MockingFrameworkReporter;
+
+/**
+ *
+ */
+public class MockingFrameworkReporterFactoryImpl extends AbstractMockingFrameworkReporterFactory {
+
+ @Override
+ protected String getImplementerClassName() {
+ return "org.powermock.api.extension.reporter" +
+ ".MockingFrameworkReporterFactoryImpl$EasyMockMockingFrameworkReporter";
+ }
+
+ private static class EasyMockMockingFrameworkReporter implements MockingFrameworkReporter {
+
+ public EasyMockMockingFrameworkReporter() {
+ // Easymock uses static methods and cglib, so call cannot be intercept and exception cannot be changes
+ // util ByteBuddy is not used. This class is create for capability.
+ }
+
+ @Override
+ public void enable() {
+ }
+
+ @Override
+ public void disable() {
+ }
+ }
+}
diff --git a/api/mockito-common/pom.xml b/api/mockito-common/pom.xml
new file mode 100644
index 0000000..c831872
--- /dev/null
+++ b/api/mockito-common/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-api</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-api-mockito-common</artifactId>
+
+ <description>
+ PowerMock API for Mockito. Common Part.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <!-- Provided since it's only needed for compile time. The consuming API's (powermock-api-mockito and powermock-api-mockito2)
+ will depend on the correct version of mockito-->
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/api/mockito-common/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java b/api/mockito-common/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java
new file mode 100644
index 0000000..61f93df
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/extension/agent/JavaAgentFrameworkRegisterImpl.java
@@ -0,0 +1,43 @@
+package org.powermock.api.extension.agent;
+
+import org.powermock.api.mockito.internal.mockcreation.AbstractMockCreator;
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.core.agent.JavaAgentFrameworkRegister;
+import org.powermock.reflect.Whitebox;
+
+/**
+ * Implementation of JavaAgentFrameworkRegister for Mockito framework.
+ */
+public class JavaAgentFrameworkRegisterImpl implements JavaAgentFrameworkRegister {
+
+ private AbstractMockCreator mockCreator;
+
+ @Override
+ public void set(JavaAgentClassRegister javaAgentClassRegister) {
+ setToPowerMockito(javaAgentClassRegister);
+ }
+
+ private void setToPowerMockito(JavaAgentClassRegister javaAgentClassRegister) {
+
+ mockCreator = getPowerMockCoreForCurrentClassLoader();
+ Whitebox.setInternalState(mockCreator, "agentClassRegister", javaAgentClassRegister);
+
+ }
+
+ private AbstractMockCreator getPowerMockCoreForCurrentClassLoader() {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ return Whitebox.getInternalState(classLoader.loadClass("org.powermock.api.mockito.internal.mockcreation.MockCreator"), "MOCK_CREATOR");
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void clear() {
+ if (mockCreator == null) {
+ throw new IllegalStateException("Cannot clear JavaAgentClassRegister. Set method has not been called.");
+ }
+ Whitebox.setInternalState(mockCreator, "agentClassRegister", (Object) null);
+ }
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java b/api/mockito-common/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
new file mode 100644
index 0000000..25c7909
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
@@ -0,0 +1,88 @@
+package org.powermock.api.extension.reporter;
+
+import org.powermock.core.reporter.MockingFrameworkReporter;
+import org.powermock.reflect.Whitebox;
+
+import static org.powermock.utils.StringJoiner.join;
+
+/**
+ * The MockingFrameworkReporterFactory which create a new instance of MockingFrameworkReporter
+ * which is loaded by current context class loader.
+ */
+ at SuppressWarnings("WeakerAccess")
+public class MockingFrameworkReporterFactoryImpl extends AbstractMockingFrameworkReporterFactory {
+
+ @Override
+ protected String getImplementerClassName() {
+ return "org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl$MockitoMockingFrameworkReporter";
+ }
+
+ @SuppressWarnings("unused")
+ private static class MockitoMockingFrameworkReporter implements MockingFrameworkReporter {
+
+ private org.mockito.exceptions.Reporter mockitoReporter;
+ private org.mockito.internal.MockitoCore mockitoCore;
+
+ private org.mockito.exceptions.Reporter getMockitoReporter(Object mockitoCore) {
+
+ return Whitebox.getInternalState(mockitoCore, "reporter");
+ }
+
+ private void setMockitoReporter(org.mockito.exceptions.Reporter reporter, org.mockito.internal.MockitoCore mockitoCore) {
+ Whitebox.setInternalState(mockitoCore, "reporter", reporter);
+ }
+
+ @Override
+ public void enable() {
+ mockitoCore = getMockitoCoreForCurrentClassLoader();
+ mockitoReporter = getMockitoReporter(mockitoCore);
+
+ PowerMockitoReporter powerMockitoReporter = new PowerMockitoReporter();
+ setMockitoReporter(powerMockitoReporter, mockitoCore);
+ }
+
+ private org.mockito.internal.MockitoCore getMockitoCoreForCurrentClassLoader() {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ return Whitebox.getInternalState(classLoader.loadClass("org.mockito.Mockito"), "MOCKITO_CORE");
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public void disable() {
+ setMockitoReporter(mockitoReporter, mockitoCore);
+ }
+ }
+
+ /**
+ * PowerMock reported for Mockito, which replace standard mockito message
+ * to specific message for cases when PowerMock is used.
+ */
+ private static class PowerMockitoReporter extends org.mockito.exceptions.Reporter {
+
+ public void missingMethodInvocation() {
+ throw new org.mockito.exceptions.misusing.MissingMethodInvocationException(join(
+ "when() requires an argument which has to be 'a method call on a mock'.",
+ "For example:",
+ " when(mock.getArticles()).thenReturn(articles);",
+ "Or 'a static method call on a prepared class`",
+ "For example:",
+ " @PrepareForTest( { StaticService.class }) ",
+ " TestClass{",
+ " public void testMethod(){",
+ " PowerMockito.mockStatic(StaticService.class);",
+ " when(StaticService.say()).thenReturn(expected);",
+ " }",
+ " }",
+ "",
+ "Also, this error might show up because:",
+ "1. inside when() you don't call method on mock but on some other object.",
+ "2. inside when() you don't call static method, but class has not been prepared.",
+ ""
+ ));
+ }
+
+ }
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/mockito/ClassNotPreparedException.java b/api/mockito-common/src/main/java/org/powermock/api/mockito/ClassNotPreparedException.java
new file mode 100644
index 0000000..496e964
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/mockito/ClassNotPreparedException.java
@@ -0,0 +1,12 @@
+package org.powermock.api.mockito;
+
+/**
+ * The exception is thrown when a user tries to mock class which is't prepared, but should be. For example it could
+ * be case mocking static call.
+ */
+public class ClassNotPreparedException extends RuntimeException {
+
+ public ClassNotPreparedException(String message) {
+ super(message);
+ }
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/mockito/expectation/reporter/MockitoPowerMockReporter.java b/api/mockito-common/src/main/java/org/powermock/api/mockito/expectation/reporter/MockitoPowerMockReporter.java
new file mode 100644
index 0000000..60f64c9
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/mockito/expectation/reporter/MockitoPowerMockReporter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.expectation.reporter;
+
+import org.powermock.api.mockito.ClassNotPreparedException;
+import org.powermock.core.reporter.PowerMockReporter;
+
+import static org.powermock.utils.StringJoiner.join;
+
+/**
+ *
+ */
+public class MockitoPowerMockReporter implements PowerMockReporter {
+ @Override
+ public <T> void classNotPrepared(Class<T> type) {
+ throw new ClassNotPreparedException(join(String.format("The class %s not prepared for test.", type
+ .getName()),
+ "To prepare this class, add class to the '@PrepareForTest' annotation.",
+ "In case if you don't use this annotation, add the annotation on class or method level. "));
+ }
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/AbstractMockCreator.java b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/AbstractMockCreator.java
new file mode 100644
index 0000000..8bfd2f2
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/AbstractMockCreator.java
@@ -0,0 +1,24 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.powermock.core.agent.JavaAgentClassRegister;
+
+import java.lang.reflect.Method;
+
+/**
+ *
+ */
+public abstract class AbstractMockCreator {
+
+ private JavaAgentClassRegister agentClassRegister;
+
+ protected abstract <T> T createMock(Class<T> type, boolean isStatic, boolean isSpy, Object delegator,
+ org.mockito.MockSettings mockSettings, Method... methods);
+
+ <T> void validateType(Class<T> type, boolean isStatic, boolean isSpy) {
+ createTypeValidator(type, isStatic, isSpy).validate();
+ }
+
+ private <T> MockTypeValidator<T> createTypeValidator(Class<T> type, boolean isStatic, boolean isSpy) {
+ return MockTypeValidatorFactory.createValidator(type, isStatic, isSpy, agentClassRegister);
+ }
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidator.java b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidator.java
new file mode 100644
index 0000000..11e2aa6
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidator.java
@@ -0,0 +1,8 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+/**
+ *
+ */
+public interface MockTypeValidator<T> {
+ void validate();
+}
diff --git a/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidatorFactory.java b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidatorFactory.java
new file mode 100644
index 0000000..a2ee6a3
--- /dev/null
+++ b/api/mockito-common/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockTypeValidatorFactory.java
@@ -0,0 +1,92 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.powermock.api.mockito.expectation.reporter.MockitoPowerMockReporter;
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.core.classloader.PowerMockModified;
+import org.powermock.core.reporter.PowerMockReporter;
+
+/**
+ *
+ */
+public class MockTypeValidatorFactory {
+
+ public static <T> MockTypeValidator<T> createValidator(Class<T> type, boolean isStatic, boolean isSpy, JavaAgentClassRegister agentClassRegister) {
+ if (!isStatic || isSpy || isLoadedByBootstrap(type)) {
+ return new NullMockTypeValidator<T>();
+ } else if (agentClassRegister == null) {
+ return new DefaultMockTypeValidator<T>(type);
+ } else {
+ return new JavaAgentMockTypeValidator<T>(type, agentClassRegister);
+ }
+
+ }
+
+ private static boolean isLoadedByBootstrap(Class type) {
+
+ return type.getClassLoader() == null;
+ }
+
+ private static class DefaultMockTypeValidator<T> extends AbstractMockTypeValidator<T> {
+
+ DefaultMockTypeValidator(Class<T> type) {
+ super(type);
+ }
+
+ @Override
+ public void validate() {
+ if (!isModifiedByPowerMock()) {
+ reporter.classNotPrepared(type);
+ }
+ }
+
+ private boolean isModifiedByPowerMock() {
+ return PowerMockModified.class.isAssignableFrom(type);
+ }
+
+
+
+ }
+
+ private static class JavaAgentMockTypeValidator<T> extends AbstractMockTypeValidator<T> {
+
+ private final JavaAgentClassRegister agentClassRegister;
+
+ private JavaAgentMockTypeValidator(Class<T> type,
+ JavaAgentClassRegister agentClassRegister) {
+ super(type);
+ this.agentClassRegister = agentClassRegister;
+ }
+
+ @Override
+ public void validate() {
+ if (!isModifiedByAgent()) {
+ reporter.classNotPrepared(type);
+ }
+ }
+
+ private boolean isModifiedByAgent() {
+ return agentClassRegister.isModifiedByAgent(type.getClassLoader(), type.getName());
+ }
+ }
+
+ private abstract static class AbstractMockTypeValidator<T> implements MockTypeValidator<T> {
+ final PowerMockReporter reporter;
+ final Class<T> type;
+
+ private AbstractMockTypeValidator(Class<T> type) {
+ this.type = type;
+ this.reporter = new MockitoPowerMockReporter();
+ }
+
+ @Override
+ public abstract void validate();
+
+ }
+
+ private static class NullMockTypeValidator<T> implements MockTypeValidator<T> {
+ @Override
+ public void validate() {
+ // NUll validator validates nothing
+ }
+ }
+}
diff --git a/api/mockito/pom.xml b/api/mockito/pom.xml
new file mode 100644
index 0000000..5657254
--- /dev/null
+++ b/api/mockito/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-api-mockito</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock API for Mockito 1.+.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/api/mockito/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java b/api/mockito/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
new file mode 100644
index 0000000..b63ce32
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.extension.listener;
+
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.MockSettings;
+import org.mockito.MockitoAnnotations.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+import org.mockito.internal.util.reflection.GenericMaster;
+import org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine;
+import org.powermock.core.spi.listener.AnnotationEnablerListener;
+import org.powermock.core.spi.support.AbstractPowerMockTestListenerBase;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import static org.mockito.Mockito.withSettings;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+/**
+ * Before each test method all fields annotated with {@link Mock},
+ * {@link org.mockito.Mock} or {@link Mock} have mock objects created for them
+ * and injected to the fields. It will also delegate to a special implementation
+ * of the {@link InjectingAnnotationEngine} in Mockito which inject's spies,
+ * captors etc.
+ * <p/>
+ * It will only inject to fields that haven't been set before (i.e that are
+ * <code>null</code>).
+ */
+ at SuppressWarnings("deprecation")
+public class AnnotationEnabler extends AbstractPowerMockTestListenerBase implements AnnotationEnablerListener {
+
+ @Override
+ public void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception {
+
+ // Mockito uses context class loader not only to load resources, but to load plugin implementers, but for
+ // other purpose default/application class loader is used. So PluginRepository and Plugin could be loaded by
+ // different class loaders. Fix will be
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+
+ standardInject(testInstance);
+ injectSpiesAndInjectToSetters(testInstance);
+ injectCaptor(testInstance);
+ } finally {
+ Thread.currentThread().setContextClassLoader(contextClassLoader);
+ }
+ }
+
+ private void injectSpiesAndInjectToSetters(Object testInstance) {
+ new PowerMockitoInjectingAnnotationEngine().process(testInstance.getClass(), testInstance);
+ }
+
+ private void injectCaptor(Object testInstance) throws Exception {
+ Set<Field> fieldsAnnotatedWithCaptor = Whitebox.getFieldsAnnotatedWith(testInstance, Captor.class);
+ for (Field field : fieldsAnnotatedWithCaptor) {
+ final Object captor = processAnnotationOn(field.getAnnotation(Captor.class), field);
+ field.set(testInstance, captor);
+ }
+ }
+
+ private void standardInject(Object testInstance) throws IllegalAccessException {
+ Set<Field> fields = Whitebox.getFieldsAnnotatedWith(testInstance, getMockAnnotations());
+ for (Field field : fields) {
+ if (field.get(testInstance) != null) {
+ continue;
+ }
+ final Class<?> type = field.getType();
+ if (field.isAnnotationPresent(org.powermock.core.classloader.annotations.Mock.class)) {
+ org.powermock.core.classloader.annotations.Mock annotation = field
+ .getAnnotation(org.powermock.core.classloader.annotations.Mock.class);
+ final String[] value = annotation.value();
+ if (value.length != 1 || !"".equals(value[0])) {
+ System.err
+ .println("PowerMockito deprecation: Use PowerMockito.spy(..) for partial mocking instead. A standard mock will be created instead.");
+ }
+ }
+
+ if (field.isAnnotationPresent(org.mockito.Mock.class)) {
+ org.mockito.Mock mockAnnotation = field.getAnnotation(org.mockito.Mock.class);
+ MockSettings mockSettings = withSettings();
+ Answers answers = mockAnnotation.answer();
+ if (answers != null) {
+ mockSettings.defaultAnswer(answers.get());
+ }
+
+ Class<?>[] extraInterfaces = mockAnnotation.extraInterfaces();
+ if (extraInterfaces != null && extraInterfaces.length > 0) {
+ mockSettings.extraInterfaces(extraInterfaces);
+ }
+
+ String name = mockAnnotation.name();
+ if (name != null && name.length() > 0) {
+ mockSettings.name(name);
+ }
+
+ field.set(testInstance, mock(type, mockSettings));
+ } else {
+ field.set(testInstance, mock(type));
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class<? extends Annotation>[] getMockAnnotations() {
+ return new Class[]{org.mockito.Mock.class, Mock.class, org.powermock.core.classloader.annotations.Mock.class};
+ }
+
+ private Object processAnnotationOn(Captor annotation, Field field) {
+ Class<?> type = field.getType();
+ if (!ArgumentCaptor.class.isAssignableFrom(type)) {
+ throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '"
+ + field.getName() + "' has wrong type\n"
+ + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class.");
+ }
+ Class cls = new GenericMaster().getGenericType(field);
+ return ArgumentCaptor.forClass(cls);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java b/api/mockito/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
new file mode 100644
index 0000000..4a41934
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.extension.proxyframework;
+
+import org.mockito.cglib.proxy.Enhancer;
+import org.mockito.cglib.proxy.Factory;
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ * CGLib proxy framework setup.
+ */
+public class ProxyFrameworkImpl implements ProxyFramework {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Class<?> getUnproxiedType(Class<?> type) {
+ Class<?> currentType = type;
+ while (isProxy(currentType)) {
+ for (Class<?> i : currentType.getInterfaces()) {
+ if (!i.getName().equals(Factory.class.getName())) {
+ return i;
+ }
+ }
+ currentType = currentType.getSuperclass();
+ }
+ return currentType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isProxy(Class<?> type) {
+ if (type == null) {
+ return false;
+ }
+ return type.getName().contains("$$EnhancerByMockitoWithCGLIB$$") || Enhancer.isEnhanced(type);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/PowerMockito.java b/api/mockito/src/main/java/org/powermock/api/mockito/PowerMockito.java
new file mode 100644
index 0000000..7e05037
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/PowerMockito.java
@@ -0,0 +1,799 @@
+/*
+s * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.answers.DoesNothing;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.expectation.ConstructorExpectationSetup;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+import org.powermock.api.mockito.internal.PowerMockitoCore;
+import org.powermock.api.mockito.internal.expectation.ConstructorAwareExpectationSetup;
+import org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup;
+import org.powermock.api.mockito.internal.expectation.DefaultMethodExpectationSetup;
+import org.powermock.api.mockito.internal.mockcreation.MockCreator;
+import org.powermock.api.mockito.internal.stubbing.answers.ChainReturns;
+import org.powermock.api.mockito.internal.verification.DefaultConstructorArgumentsVerfication;
+import org.powermock.api.mockito.internal.verification.DefaultPrivateMethodVerification;
+import org.powermock.api.mockito.internal.verification.VerifyNoMoreInteractions;
+import org.powermock.api.mockito.verification.ConstructorArgumentsVerification;
+import org.powermock.api.mockito.verification.PrivateMethodVerification;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * PowerMockito extends Mockito functionality with several new features such as
+ * mocking static and private methods and more. Use PowerMock instead of Mockito
+ * where applicable.
+ *
+ * @see Mockito
+ */
+public class PowerMockito extends MemberModifier {
+ private static final String NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE = "No instantiation of class %s was recorded during the test. Note that only expected object creations (e.g. those using whenNew(..)) can be verified.";
+ private static final PowerMockitoCore POWERMOCKITO_CORE = new PowerMockitoCore();
+
+ /**
+ * Enable static mocking for all methods of a class.
+ *
+ * @param type
+ * the class to enable static mocking
+ */
+ public static synchronized void mockStatic(Class<?> type, Class<?>... types) {
+ MockCreator.mock(type, true, false, null, null, (Method[]) null);
+ if(types != null && types.length > 0) {
+ for (Class<?> aClass : types) {
+ MockCreator.mock(aClass, true, false, null, null, (Method[]) null);
+ }
+ }
+ }
+
+ /**
+ * Creates class mock with a specified strategy for its answers to
+ * interactions. It's quite advanced feature and typically you don't need it
+ * to write decent tests. However it can be helpful when working with legacy
+ * systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b>
+ * stub the method call.
+ *
+ * <pre>
+ * mockStatic(Foo.class, RETURNS_SMART_NULLS);
+ * mockStatic(Foo.class, new YourOwnAnswer());
+ * </pre>
+ *
+ * @param classMock
+ * class to mock
+ * @param defaultAnswer
+ * default answer for unstubbed methods
+ *
+ * @return mock object
+ */
+ public static void mockStatic(Class<?> classMock, @SuppressWarnings("rawtypes") Answer defaultAnswer) {
+ mockStatic(classMock, withSettings().defaultAnswer(defaultAnswer));
+ }
+
+ /**
+ * Creates a class mock with some non-standard settings.
+ * <p>
+ * The number of configuration points for a mock grows so we need a fluent
+ * way to introduce new configuration without adding more and more
+ * overloaded PowerMockito.mockStatic() methods. Hence {@link MockSettings}.
+ *
+ * <pre>
+ * mockStatic(Listener.class, withSettings()
+ * .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+ * );
+ * </pre>
+ *
+ * <b>Use it carefully and occasionally</b>. What might be reason your test
+ * needs non-standard mocks? Is the code under test so complicated that it
+ * requires non-standard mocks? Wouldn't you prefer to refactor the code
+ * under test so it is testable in a simple way?
+ * <p>
+ * See also {@link Mockito#withSettings()}
+ *
+ * @param classToMock
+ * class to mock
+ * @param mockSettings
+ * additional mock settings
+ * @return mock object
+ */
+ public static void mockStatic(Class<?> classToMock, MockSettings mockSettings) {
+ MockCreator.mock(classToMock, true, false, null, mockSettings, (Method[]) null);
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods.
+ *
+ * @param <T>
+ * the type of the mock object
+ * @param type
+ * the type of the mock object
+ * @return the mock object.
+ */
+ public static synchronized <T> T mock(Class<T> type) {
+ return MockCreator.mock(type, false, false, null, null, (Method[]) null);
+ }
+
+ /**
+ * Creates mock with a specified strategy for its answers to interactions.
+ * It's quite advanced feature and typically you don't need it to write
+ * decent tests. However it can be helpful when working with legacy systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b>
+ * stub the method call.
+ *
+ * <pre>
+ * Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+ * Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </pre>
+ *
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ * </p>
+ *
+ * @param classToMock
+ * class or interface to mock
+ * @param defaultAnswer
+ * default answer for unstubbed methods
+ *
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, @SuppressWarnings("rawtypes") Answer defaultAnswer) {
+ return mock(classToMock, withSettings().defaultAnswer(defaultAnswer));
+ }
+
+ /**
+ * Creates a mock with some non-standard settings.
+ * <p>
+ * The number of configuration points for a mock grows so we need a fluent
+ * way to introduce new configuration without adding more and more
+ * overloaded Mockito.mock() methods. Hence {@link MockSettings}.
+ *
+ * <pre>
+ * Listener mock = mock(Listener.class, withSettings()
+ * .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+ * );
+ * </pre>
+ *
+ * <b>Use it carefully and occasionally</b>. What might be reason your test
+ * needs non-standard mocks? Is the code under test so complicated that it
+ * requires non-standard mocks? Wouldn't you prefer to refactor the code
+ * under test so it is testable in a simple way?
+ * <p>
+ * See also {@link Mockito#withSettings()}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param classToMock
+ * class or interface to mock
+ * @param mockSettings
+ * additional mock settings
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
+ return MockCreator.mock(classToMock, false, false, null, mockSettings, (Method[]) null);
+ }
+
+ /**
+ * Spy on objects that are final or otherwise not "spyable" from
+ * normal Mockito.
+ *
+ * @see Mockito#spy(Object)
+ *
+ * @param <T>
+ * the type of the mock object
+ * @param object
+ * the object to spy on
+ * @return the spy object.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T spy(T object) {
+ return MockCreator.mock((Class<T>) Whitebox.getType(object), false, true, object, null, (Method[]) null);
+ }
+
+ /**
+ * Spy on classes (not "spyable" from normal Mockito).
+ *
+ * @see Mockito#spy(Object)
+ *
+ * @param <T>
+ * the type of the class mock
+ * @param type
+ * the type of the class mock
+ */
+ public static synchronized <T> void spy(Class<T> type) {
+ MockCreator.mock(type, true, true, type, null, (Method[]) null);
+ }
+
+ /**
+ * Verifies certain behavior <b>happened once</b>
+ * <p>
+ * Alias to <code>verifyStatic(times(1))</code> E.g:
+ *
+ * <pre>
+ * verifyStatic();
+ * ClassWithStaticMethod.someStaticMethod("some arg");
+ * </pre>
+ *
+ * Above is equivalent to:
+ *
+ * <pre>
+ * verifyStatic(times(1));
+ * ClassWithStaticMethod.someStaticMethod("some arg");
+ * </pre>
+ *
+ * <p>
+ * Although it is possible to verify a stubbed invocation, usually <b>it's
+ * just redundant</b>. Let's say you've stubbed foo.bar(). If your code
+ * cares what foo.bar() returns then something else breaks(often before even
+ * verify() gets executed). If your code doesn't care what get(0) returns
+ * then it should not be stubbed.
+ */
+ public static synchronized void verifyStatic() {
+ verifyStatic(times(1));
+ }
+
+ /**
+ * Verifies certain behavior happened at least once / exact number of times
+ * / never. E.g:
+ *
+ * <pre>
+ * verifyStatic(times(5));
+ * ClassWithStaticMethod.someStaticMethod("was called five times");
+ *
+ * verifyStatic(atLeast(2));
+ * ClassWithStaticMethod.someStaticMethod("was called at least two times");
+ *
+ * //you can use flexible argument matchers, e.g:
+ * verifyStatic(atLeastOnce());
+ * ClassWithStaticMethod.someMethod(<b>anyString()</b>);
+ * </pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ *
+ * @param verificationMode
+ * times(x), atLeastOnce() or never()
+ */
+ public static synchronized void verifyStatic(VerificationMode verificationMode) {
+ Whitebox.getInternalState(Mockito.class, MockingProgress.class).verificationStarted(
+ POWERMOCKITO_CORE.wrapInStaticVerificationMode(verificationMode));
+ }
+
+ /**
+ * Verify a private method invocation for an instance.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Object object) throws Exception {
+ return verifyPrivate(object, times(1));
+ }
+
+ /**
+ * Verify a private method invocation with a given verification mode.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Object object, VerificationMode verificationMode)
+ throws Exception {
+ Whitebox.getInternalState(Mockito.class, MockingProgress.class).verificationStarted(
+ POWERMOCKITO_CORE.wrapInMockitoSpecificVerificationMode(object, verificationMode));
+ return new DefaultPrivateMethodVerification(object);
+ }
+
+ /**
+ * Verify a private method invocation for a class.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Class<?> clazz) throws Exception {
+ return verifyPrivate((Object) clazz);
+ }
+
+ /**
+ * Verify a private method invocation for a class with a given verification
+ * mode.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Class<?> clazz, VerificationMode verificationMode)
+ throws Exception {
+ return verifyPrivate((Object) clazz, verificationMode);
+ }
+
+ /**
+ * Verifies certain behavior <b>happened once</b>
+ * <p>
+ * Alias to <code>verifyNew(mockClass, times(1))</code> E.g:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class);
+ * </pre>
+ *
+ * Above is equivalent to:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class, times(1));
+ * </pre>
+ *
+ * <p>
+ *
+ * @param mock
+ * Class mocked by PowerMock.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> ConstructorArgumentsVerification verifyNew(Class<T> mock) {
+ if (mock == null) {
+ throw new IllegalArgumentException("Class to verify cannot be null");
+ }
+ NewInvocationControl<?> invocationControl = MockRepository.getNewInstanceControl(mock);
+ if (invocationControl == null) {
+ throw new IllegalStateException(String.format(NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE, Whitebox.getType(
+ mock).getName()));
+ }
+ invocationControl.verify();
+ return new DefaultConstructorArgumentsVerfication<T>((NewInvocationControl<T>) invocationControl, mock);
+ }
+
+ /**
+ * Verifies certain behavior happened at least once / exact number of times
+ * / never. E.g:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class, times(5));
+ *
+ * verifyNew(ClassWithStaticMethod.class, atLeast(2));
+ *
+ * //you can use flexible argument matchers, e.g:
+ * verifyNew(ClassWithStaticMethod.class, atLeastOnce());
+ * </pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ *
+ * @param mock
+ * to be verified
+ * @param mode
+ * times(x), atLeastOnce() or never()
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> ConstructorArgumentsVerification verifyNew(Class<?> mock, VerificationMode mode) {
+ if (mock == null) {
+ throw new IllegalArgumentException("Class to verify cannot be null");
+ } else if (mode == null) {
+ throw new IllegalArgumentException("Verify mode cannot be null");
+ }
+ NewInvocationControl<?> invocationControl = MockRepository.getNewInstanceControl(mock);
+ MockRepository.putAdditionalState("VerificationMode", POWERMOCKITO_CORE.wrapInMockitoSpecificVerificationMode(
+ mock, mode));
+ if (invocationControl == null) {
+ throw new IllegalStateException(String.format(NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE, Whitebox.getType(
+ mock).getName()));
+ }
+ try {
+ invocationControl.verify();
+ } finally {
+ MockRepository.removeAdditionalState("VerificationMode");
+ }
+ return new DefaultConstructorArgumentsVerfication<T>((NewInvocationControl<T>) invocationControl, mock);
+ }
+
+ /**
+ * Expect calls to private methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Object instance, String methodName, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(instance, methodName, arguments));
+ }
+
+ /**
+ * Expect calls to private methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> WithOrWithoutExpectedArguments<T> when(Object instance, Method method) throws Exception {
+ return new DefaultMethodExpectationSetup<T>(instance, method);
+ }
+
+ /**
+ * Expect calls to private static methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> WithOrWithoutExpectedArguments<T> when(Class<?> cls, Method method) throws Exception {
+ return new DefaultMethodExpectationSetup<T>(cls, method);
+ }
+
+ /**
+ * Expect calls to private methods without having to specify the method
+ * name. The method will be looked up using the parameter types (if
+ * possible).
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Object instance, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(instance, arguments));
+ }
+
+ /**
+ * Expect a static private or inner class method call.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Class<?> clazz, String methodToExpect, Object... arguments)
+ throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(clazz, methodToExpect, arguments));
+ }
+
+ /**
+ * Expect calls to private static methods without having to specify the
+ * method name. The method will be looked up using the parameter types if
+ * possible
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Class<?> klass, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(klass, arguments));
+ }
+
+ /**
+ * Just delegates to the original {@link Mockito#when(Object)} method.
+ *
+ * @see {@link Mockito#when(Object)}
+ */
+ public static <T> OngoingStubbing<T> when(T methodCall) {
+ return Mockito.when(methodCall);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ */
+ public static synchronized <T> WithOrWithoutExpectedArguments<T> whenNew(Constructor<T> ctor) {
+ return new ConstructorAwareExpectationSetup<T>(ctor);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ */
+ public static synchronized <T> ConstructorExpectationSetup<T> whenNew(Class<T> type) {
+ return new DefaultConstructorExpectationSetup<T>(type);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations for private member
+ * (inner) classes, local or anonymous classes. For example you might want
+ * to throw an exception or return a mock.
+ *
+ * @param fullyQualifiedName
+ * The fully-qualified name of the inner/local/anonymous type to
+ * expect.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> ConstructorExpectationSetup<T> whenNew(String fullyQualifiedName) throws Exception {
+ final Class<T> forName = (Class<T>) Class.forName(fullyQualifiedName);
+ return new DefaultConstructorExpectationSetup<T>(forName);
+ }
+
+ /**
+ * Checks if any of given mocks (can be both instance and class mocks) has
+ * any unverified interaction. Delegates to the orignal
+ * {@link Mockito#verifyNoMoreInteractions(Object...)} if the mock is not a
+ * PowerMockito mock.
+ * <p>
+ * You can use this method after you verified your mocks - to make sure that
+ * nothing else was invoked on your mocks.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates
+ * the intent well.
+ * <p>
+ * Stubbed invocations (if called) are also treated as interactions.
+ * <p>
+ * A word of <b>warning</b>: Some users who did a lot of classic,
+ * expect-run-verify mocking tend to use verifyNoMoreInteractions() very
+ * often, even in every test method. verifyNoMoreInteractions() is not
+ * recommended to use in every test method. verifyNoMoreInteractions() is a
+ * handy assertion from the interaction testing toolkit. Use it only when
+ * it's relevant. Abusing it leads to overspecified, less maintainable
+ * tests. You can find further reading <a href=
+ * "http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/"
+ * >here</a>.
+ * <p>
+ * This method will also detect unverified invocations that occurred before
+ * the test method, for example: in setUp(), @Before method or in
+ * constructor. Consider writing nice code that makes interactions only in
+ * test methods.
+ *
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * //interactions
+ * mock.doSomething();
+ * mock.doSomethingUnexpected();
+ *
+ * //verification
+ * verify(mock).doSomething();
+ *
+ * //following will fail because 'doSomethingUnexpected()' is unexpected
+ * verifyNoMoreInteractions(mock);
+ *
+ * </pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks
+ * to be verified
+ */
+ public static void verifyNoMoreInteractions(Object... mocks) {
+ VerifyNoMoreInteractions.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * Verifies that no interactions happened on given mocks (can be both
+ * instance and class mocks). Delegates to the orignal
+ * {@link Mockito#verifyNoMoreInteractions(Object...)} if the mock is not a
+ * PowerMockito mock.
+ *
+ * <pre>
+ * verifyZeroInteractions(mockOne, mockTwo);
+ * </pre>
+ *
+ * This method will also detect invocations that occurred before the test
+ * method, for example: in setUp(), @Before method or in constructor.
+ * Consider writing nice code that makes interactions only in test methods.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates
+ * the intent well.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks
+ * to be verified
+ */
+ public static void verifyZeroInteractions(Object... mocks) {
+ VerifyNoMoreInteractions.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * Use doAnswer() when you want to stub a void method with generic
+ * {@link Answer}.
+ * <p>
+ * Stubbing voids requires different approach from
+ * {@link Mockito#when(Object)} because the compiler does not like void
+ * methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doAnswer(new Answer() {
+ * public Object answer(InvocationOnMock invocation) {
+ * Object[] args = invocation.getArguments();
+ * Mock mock = invocation.getMock();
+ * return null;
+ * }
+ * }).when(mock).someMethod();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param answer
+ * to answer when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doAnswer(Answer<?> answer) {
+ return POWERMOCKITO_CORE.doAnswer(answer);
+ }
+
+ /**
+ * Use doThrow() when you want to stub the void method with an exception.
+ * <p>
+ * Stubbing voids requires different approach from
+ * {@link Mockito#when(Object)} because the compiler does not like void
+ * methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(mock).someVoidMethod();
+ * </pre>
+ *
+ * @param toBeThrown
+ * to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doThrow(Throwable toBeThrown) {
+ return POWERMOCKITO_CORE.doAnswer(new ThrowsException(toBeThrown));
+ }
+
+ /**
+ * Use doCallRealMethod() when you want to call the real implementation of a
+ * method.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>: Object
+ * oriented programming is more less tackling complexity by dividing the
+ * complexity into separate, specific, SRPy objects. How does partial mock
+ * fit into this paradigm? Well, it just doesn't... Partial mock usually
+ * means that the complexity has been moved to a different method on the
+ * same object. In most cases, this is not the way you want to design your
+ * application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy: dealing with
+ * code you cannot change easily (3rd party interfaces, interim refactoring
+ * of legacy code etc.) However, I wouldn't use partial mocks for new,
+ * test-driven & well-designed code.
+ * <p>
+ * See also javadoc {@link Mockito#spy(Object)} to find out more about
+ * partial mocks. <b>Mockito.spy() is a recommended way of creating partial
+ * mocks.</b> The reason is it guarantees real methods are called against
+ * correctly constructed object because you're responsible for constructing
+ * the object passed to spy() method.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * Foo mock = mock(Foo.class);
+ * doCallRealMethod().when(mock).someVoidMethod();
+ *
+ * // this will call the real implementation of Foo.someVoidMethod()
+ * mock.someVoidMethod();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doCallRealMethod() {
+ return POWERMOCKITO_CORE.doAnswer(new CallsRealMethods());
+ }
+
+ /**
+ * Use doNothing() for setting void methods to do nothing. <b>Beware that
+ * void methods on mocks do nothing by default!</b> However, there are rare
+ * situations when doNothing() comes handy:
+ * <p>
+ * 1. Stubbing consecutive calls on a void method:
+ *
+ * <pre>
+ * doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();
+ *
+ * //does nothing the first time:
+ * mock.someVoidMethod();
+ *
+ * //throws RuntimeException the next time:
+ * mock.someVoidMethod();
+ * </pre>
+ *
+ * 2. When you spy real objects and you want the void method to do nothing:
+ *
+ * <pre>
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //let's make clear() do nothing
+ * doNothing().when(spy).clear();
+ *
+ * spy.add("one");
+ *
+ * //clear() does nothing, so the list still contains "one"
+ * spy.clear();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doNothing() {
+ return POWERMOCKITO_CORE.doAnswer(new DoesNothing());
+ }
+
+ /**
+ * Use doReturn() in those rare occasions when you cannot use
+ * {@link Mockito#when(Object)}.
+ * <p>
+ * <b>Beware that {@link Mockito#when(Object)} is always recommended for
+ * stubbing because it is argument type-safe and more readable</b>
+ * (especially when stubbing consecutive calls).
+ * <p>
+ * Here are those rare occasions when doReturn() comes handy:
+ * <p>
+ *
+ * 1. When spying real objects and calling real methods on a spy brings side
+ * effects
+ *
+ * <pre>
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("foo").when(spy).get(0);
+ * </pre>
+ *
+ * 2. Overriding a previous exception-stubbing:
+ *
+ * <pre>
+ * when(mock.foo()).thenThrow(new RuntimeException());
+ *
+ * //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
+ * when(mock.foo()).thenReturn("bar");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("bar").when(mock).foo();
+ * </pre>
+ *
+ * Above scenarios shows a tradeoff of Mockito's ellegant syntax. Note that
+ * the scenarios are very rare, though. Spying should be sporadic and
+ * overriding exception-stubbing is very rare.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param toBeReturned
+ * to be returned when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doReturn(Object toBeReturned) {
+ return POWERMOCKITO_CORE.doAnswer(new Returns(toBeReturned));
+ }
+
+ public static PowerMockitoStubber doReturn(Object toBeReturned, Object... othersToBeReturned) {
+ if (othersToBeReturned != null && othersToBeReturned.length == 0) {
+ return doReturn(toBeReturned);
+ }
+ return POWERMOCKITO_CORE.doAnswer(new ChainReturns(toBeReturned, othersToBeReturned));
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java
new file mode 100644
index 0000000..0442b1c
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface ConstructorExpectationSetup<T> extends WithOrWithoutExpectedArguments<T>, WithExpectedParameterTypes<T>, WithAnyArguments<T> {
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java
new file mode 100644
index 0000000..4d10b9e
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
+
+import java.lang.reflect.Method;
+
+/**
+ * Setup stubbing for private or void methods in final class, final void
+ * methods, or static (final) methods.
+ */
+public interface PowerMockitoStubber extends Stubber {
+ /**
+ * Allows to choose a static method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(StaticList.class);
+ * StaticList.clear();
+ *
+ * //following throws RuntimeException:
+ * StaticList.clear();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ void when(Class<?> classMock);
+
+ /**
+ * Allows to mock a private instance method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, method("myMethod")).withNoArguments();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception;
+
+ /**
+ * Allows to mock a private instance method based on the parameters when
+ * stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(T mock, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a private instance method based on method name and
+ * parameters when stubbing in doThrow()|doAnswer()|doNothing()|doReturn()
+ * style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, "methodName", parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(T mock, String methodToExpect, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a static private method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, method("myMethod")).withNoArguments();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception;
+
+ /**
+ * Allows to mock a static private method based on the parameters when
+ * stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(Class<T> classMock, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a static private method based on method name and
+ * parameters when stubbing in doThrow()|doAnswer()|doNothing()|doReturn()
+ * style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, "methodName", parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(Class<T> classMock, String methodToExpect, Object... parameters) throws Exception;
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java
new file mode 100644
index 0000000..8a5558e
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */package org.powermock.api.mockito.expectation;
+
+public interface PrivatelyExpectedArguments {
+ <T> void withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+ <T> void withNoArguments() throws Exception;
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java
new file mode 100644
index 0000000..cfad9d6
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithAnyArguments<T> {
+
+ OngoingStubbing<T> withAnyArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java
new file mode 100644
index 0000000..5c7576a
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithExpectedArguments<T> {
+
+ OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java
new file mode 100644
index 0000000..a331e6d
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface WithExpectedParameterTypes<T> {
+
+ WithExpectedArguments<T> withParameterTypes(Class<?> parameterType, Class<?>... additionalParameterTypes);
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java
new file mode 100644
index 0000000..5a2987a
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface WithOrWithoutExpectedArguments<T> extends WithExpectedArguments<T>, WithoutExpectedArguments<T> {
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java
new file mode 100644
index 0000000..2492161
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithoutExpectedArguments<T> {
+
+ OngoingStubbing<T> withNoArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java
new file mode 100644
index 0000000..40535de
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal;
+
+import org.mockito.Mockito;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.stubbing.Answer;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl;
+import org.powermock.api.mockito.internal.verification.StaticMockAwareVerificationMode;
+import org.powermock.reflect.Whitebox;
+
+public class PowerMockitoCore {
+ @SuppressWarnings("rawtypes")
+ public PowerMockitoStubber doAnswer(Answer answer) {
+ // We change the context classloader to the current CL in order for the Mockito
+ // framework to load it's plugins (such as MockMaker) correctly.
+ final ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ try {
+ getMockingProgress().stubbingStarted();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCL);
+ }
+ getMockingProgress().resetOngoingStubbing();
+ return (PowerMockitoStubber) new PowerMockitoStubberImpl().doAnswer(answer);
+ }
+
+ private MockingProgress getMockingProgress() {
+ return Whitebox.getInternalState(Mockito.class, MockingProgress.class);
+ }
+
+ public MockAwareVerificationMode wrapInMockitoSpecificVerificationMode(Object mock, VerificationMode mode) {
+ return new MockAwareVerificationMode(mock, mode);
+ }
+
+ public MockAwareVerificationMode wrapInStaticVerificationMode(VerificationMode mode) {
+ return new StaticMockAwareVerificationMode(mode);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java
new file mode 100644
index 0000000..205df85
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.configuration;
+
+import org.mockito.Mock;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+
+/**
+ * The same as {@link InjectingAnnotationEngine} with the exception that it
+ * doesn't create/injects mocks annotated with the standard annotations such as
+ * {@link Mock}.
+ */
+public class PowerMockitoInjectingAnnotationEngine extends InjectingAnnotationEngine {
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void process(Class<?> context, Object testClass) {
+ // this will create @Spies:
+ new PowerMockitoSpyAnnotationEngine().process(context, testClass);
+
+ // this injects mocks
+ injectMocks(testClass);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java
new file mode 100644
index 0000000..1045bc5
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.configuration;
+
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.SpyAnnotationEngine;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Field;
+
+/**
+ * More or less a copy of the {@link SpyAnnotationEngine} but it uses
+ * {@link PowerMockito#spy(Object)} instead.
+ */
+public class PowerMockitoSpyAnnotationEngine extends SpyAnnotationEngine {
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void process(Class<?> context, Object testClass) {
+ Field[] fields = context.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Spy.class)) {
+ try {
+ Whitebox.invokeMethod(this, Spy.class, field, new Class<?>[] { Mock.class,
+ org.mockito.MockitoAnnotations.Mock.class, Captor.class });
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e1) {
+ throw new RuntimeException(e1);
+ }
+ boolean wasAccessible = field.isAccessible();
+ field.setAccessible(true);
+ try {
+ Object instance = field.get(testClass);
+ if (instance == null) {
+ throw new MockitoException("Cannot create a @Spy for '" + field.getName()
+ + "' field because the *instance* is missing\n" + "Example of correct usage of @Spy:\n"
+ + " @Spy List mock = new LinkedList();\n");
+ }
+ field.set(testClass, PowerMockito.spy(instance));
+ } catch (IllegalAccessException e) {
+ throw new MockitoException("Problems initiating spied field " + field.getName(), e);
+ } finally {
+ field.setAccessible(wasAccessible);
+ }
+ }
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java
new file mode 100644
index 0000000..afd7bc1
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java
@@ -0,0 +1,15 @@
+package org.powermock.api.mockito.internal.exceptions;
+
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+
+public class StackTraceCleanerProvider implements org.mockito.plugins.StackTraceCleanerProvider {
+ @Override
+ public StackTraceCleaner getStackTraceCleaner(final StackTraceCleaner defaultCleaner) {
+ return new StackTraceCleaner() {
+ @Override
+ public boolean isOut(StackTraceElement candidate) {
+ return defaultCleaner.isOut(candidate) || candidate.getClassName().startsWith("org.powermock.api.mockito");
+ }
+ };
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java
new file mode 100644
index 0000000..bfcde14
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+
+import java.lang.reflect.Constructor;
+
+public class ConstructorAwareExpectationSetup<T> implements WithOrWithoutExpectedArguments<T> {
+
+ private final Constructor<T> ctor;
+
+ public ConstructorAwareExpectationSetup(Constructor<T> ctor) {
+ if (ctor == null) {
+ throw new IllegalArgumentException("Constructor to expect cannot be null");
+ }
+ this.ctor = ctor;
+ }
+
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ return setupExpectation().withArguments(firstArgument, additionalArguments);
+ }
+
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return setupExpectation().withNoArguments();
+ }
+
+ private DefaultConstructorExpectationSetup<T> setupExpectation() {
+ DefaultConstructorExpectationSetup<T> setup = new DefaultConstructorExpectationSetup<T>(ctor.getDeclaringClass());
+ setup.setParameterTypes(ctor.getParameterTypes());
+ return setup;
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java
new file mode 100644
index 0000000..2fe6021
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Matchers;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.ConstructorExpectationSetup;
+import org.powermock.api.mockito.expectation.WithExpectedArguments;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.api.mockito.internal.mockcreation.MockCreator;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.tests.utils.ArrayMerger;
+import org.powermock.tests.utils.impl.ArrayMergerImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class DefaultConstructorExpectationSetup<T> implements ConstructorExpectationSetup<T> {
+
+ private Class<?>[] parameterTypes = null;
+ private final Class<T> mockType;
+ private final ArrayMerger arrayMerger;
+
+ public DefaultConstructorExpectationSetup(Class<T> mockType) {
+ this.mockType = mockType;
+ arrayMerger = new ArrayMergerImpl();
+ }
+
+ void setParameterTypes(Class<?>[] parameterTypes) {
+ this.parameterTypes = parameterTypes;
+ }
+
+ OngoingStubbing<T> withArguments(Object[] additionalArguments) throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, additionalArguments);
+ }
+
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, arrayMerger.mergeArrays(Object.class, new Object[]{firstArgument},
+ additionalArguments));
+ }
+
+ @Override
+ public OngoingStubbing<T> withAnyArguments() throws Exception {
+ if (mockType == null) {
+ throw new IllegalArgumentException("Class to expected cannot be null");
+ }
+ final Class<T> unmockedType = (Class<T>) WhiteboxImpl.getUnmockedType(mockType);
+ final Constructor<?>[] allConstructors = WhiteboxImpl.getAllConstructors(unmockedType);
+ final Constructor<?> constructor = allConstructors[0];
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ Object[] paramArgs = new Object[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Class<?> paramType = parameterTypes[i];
+ paramArgs[i] = Matchers.any(paramType);
+ }
+ final OngoingStubbing<T> ongoingStubbing = createNewSubstituteMock(mockType, parameterTypes, paramArgs);
+ Constructor<?>[] otherCtors = new Constructor<?>[allConstructors.length-1];
+ System.arraycopy(allConstructors, 1, otherCtors, 0, allConstructors.length-1);
+ return new DelegatingToConstructorsOngoingStubbing<T>(otherCtors, ongoingStubbing);
+ }
+
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, new Object[0]);
+ }
+
+ @Override
+ public WithExpectedArguments<T> withParameterTypes(Class<?> parameterType, Class<?>... additionalParameterTypes) {
+ this.parameterTypes = arrayMerger.mergeArrays(Class.class, new Class<?>[] { parameterType }, additionalParameterTypes);
+ return this;
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static <T> OngoingStubbing<T> createNewSubstituteMock(Class<T> type, Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ if (type == null) {
+ throw new IllegalArgumentException("type cannot be null");
+ }
+
+ final Class<T> unmockedType = (Class<T>) WhiteboxImpl.getUnmockedType(type);
+ if (parameterTypes == null) {
+ WhiteboxImpl.findUniqueConstructorOrThrowException(type, arguments);
+ } else {
+ WhiteboxImpl.getConstructor(unmockedType, parameterTypes);
+ }
+
+ /*
+ * Check if this type has been mocked before
+ */
+ NewInvocationControl<OngoingStubbing<T>> newInvocationControl = (NewInvocationControl<OngoingStubbing<T>>) MockRepository
+ .getNewInstanceControl(unmockedType);
+ if (newInvocationControl == null) {
+ InvocationSubstitute<T> mock = MockCreator.mock(InvocationSubstitute.class, false, false, null, null, (Method[]) null);
+ newInvocationControl = new MockitoNewInvocationControl(mock);
+ MockRepository.putNewInstanceControl(type, newInvocationControl);
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(WhiteboxImpl.getUnmockedType(type));
+ }
+
+ return newInvocationControl.expectSubstitutionLogic(arguments);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java
new file mode 100644
index 0000000..d65b804
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Mockito;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+
+import java.lang.reflect.Method;
+
+public class DefaultMethodExpectationSetup<T> implements WithOrWithoutExpectedArguments<T> {
+
+ private final Object object;
+
+ private final Method method;
+
+ public DefaultMethodExpectationSetup(Object object, Method method) {
+ if (object == null) {
+ throw new IllegalArgumentException("object to expect cannot be null");
+ } else if (method == null) {
+ throw new IllegalArgumentException("method to expect cannot be null");
+ }
+ this.object = object;
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object, firstArgument));
+ } else {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object, join(firstArgument, additionalArguments)));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object));
+ }
+
+ private static Object[] join(Object o, Object[] array) {
+ Object[] res = new Object[array.length + 1];
+ res[0] = o;
+ System.arraycopy(array, 0, res, 1, array.length);
+ return res;
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java
new file mode 100644
index 0000000..4186441
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.powermock.api.mockito.expectation.PrivatelyExpectedArguments;
+
+import java.lang.reflect.Method;
+
+public class DefaultPrivatelyExpectedArguments implements PrivatelyExpectedArguments {
+
+ private final Method method;
+ private final Object mock;
+
+ public DefaultPrivatelyExpectedArguments(Object mock, Method method) {
+ this.mock = mock;
+ this.method = method;
+ method.setAccessible(true);
+ }
+
+ @Override
+ public <T> void withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ method.invoke(mock, firstArgument);
+ } else {
+ Object[] allArgs = new Object[additionalArguments.length + 1];
+ allArgs[0] = firstArgument;
+ if (additionalArguments.length > 0) {
+ System.arraycopy(additionalArguments, 0, allArgs, 1, additionalArguments.length);
+ }
+ method.invoke(mock, allArgs);
+ }
+ }
+
+ @Override
+ public <T> void withNoArguments() throws Exception {
+ method.invoke(mock);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java
new file mode 100644
index 0000000..601ea41
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Matchers;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.core.spi.support.InvocationSubstitute;
+
+import java.lang.reflect.Constructor;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * Implementation of OngoingStubbing that delegates invocations to all supplied ctors
+ * @param <T>
+ */
+public class DelegatingToConstructorsOngoingStubbing<T> implements OngoingStubbing<T>{
+
+ private final OngoingStubbing<T> stubbing;
+ private final Constructor<?>[] ctors;
+
+ public DelegatingToConstructorsOngoingStubbing(Constructor<?>[] ctors, OngoingStubbing<T> stubbing) {
+ if(stubbing == null) {
+ throw new IllegalArgumentException("Internal error: Ongoing stubbing must be provided");
+ }
+ this.ctors = ctors;
+ this.stubbing = stubbing;
+ }
+
+ @Override
+ public OngoingStubbing<T> thenReturn(final T value) {
+ stubbing.thenReturn(value);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenReturn(value);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenReturn(final T value, final T... values) {
+ stubbing.thenReturn(value, values);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenReturn(value, values);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenThrow(final Throwable... throwables) {
+ stubbing.thenThrow(throwables);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenThrow(throwables);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenThrow(final Class<? extends Throwable>... throwableClasses) {
+ stubbing.thenThrow(throwableClasses);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenThrow(throwableClasses);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenCallRealMethod() {
+ stubbing.thenCallRealMethod();
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenCallRealMethod();
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenAnswer(final Answer<?> answer) {
+ stubbing.thenAnswer(answer);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenAnswer(answer);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> then(final Answer<?> answer) {
+ stubbing.then(answer);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.then(answer);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public <M> M getMock() {
+ return stubbing.getMock();
+ }
+
+
+ private abstract class InvokeStubMethod {
+ public OngoingStubbing<T> invoke() {
+ final InvocationSubstitute<T> mock = stubbing.getMock();
+ for (Constructor<?> constructor : ctors) {
+ final Class<?>[] parameterTypesForCtor = constructor.getParameterTypes();
+ Object[] paramArgs = new Object[parameterTypesForCtor.length];
+ for (int i = 0; i < parameterTypesForCtor.length; i++) {
+ Class<?> paramType = parameterTypesForCtor[i];
+ paramArgs[i] = Matchers.any(paramType);
+ }
+ try {
+ final OngoingStubbing<T> when = when(mock.performSubstitutionLogic(paramArgs));
+ performStubbing(when);
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error",e);
+ }
+ }
+
+ return stubbing;
+ }
+
+ public abstract void performStubbing(OngoingStubbing<T> when);
+
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java
new file mode 100644
index 0000000..4cd3e97
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.invocation.MockHandler;
+import org.mockito.stubbing.Stubber;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.expectation.PrivatelyExpectedArguments;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Extension of the standard Mocktio stubber implementation that also support
+ * PowerMockito created mocks.
+ */
+public class PowerMockitoStubberImpl extends StubberImpl implements PowerMockitoStubber {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void when(Class<?> classMock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getStaticMethodInvocationControl(classMock);
+ addAnswersForStubbing(invocationControl);
+ }
+
+ /**
+ * Supports PowerMockito mocks. If <code>mock</code> is not a PowerMockito
+ * mock it will delegate to Mockito.
+ *
+ * @see Stubber#when(Object)
+ */
+ @Override
+ public <T> T when(T instanceMock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getInstanceMethodInvocationControl(instanceMock);
+ final T returnValue;
+ if (invocationControl == null) {
+ returnValue = super.when(instanceMock);
+ } else {
+ addAnswersForStubbing(invocationControl);
+ returnValue = instanceMock;
+ }
+ return returnValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addAnswersForStubbing(MockitoMethodInvocationControl invocationControl) {
+ final MockHandler mockHandler = invocationControl.getInvocationHandler().getHandler();
+ final List list = Whitebox.getInternalState(this, List.class);
+ try {
+ Whitebox.invokeMethod(mockHandler, "setAnswersForStubbing", list);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public <T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception {
+ assertNotNull(mock, "mock");
+ assertNotNull(method, "Method");
+ prepareForStubbing(mock);
+ return new DefaultPrivatelyExpectedArguments(mock, method);
+ }
+
+ @Override
+ public <T> void when(T mock, Object... arguments) throws Exception {
+ assertNotNull(mock, "mock");
+ prepareForStubbing(mock);
+ Whitebox.invokeMethod(mock, arguments);
+ }
+
+ @Override
+ public <T> void when(T mock, String methodToExpect, Object... arguments) throws Exception {
+ assertNotNull(mock, "mock");
+ assertNotNull(methodToExpect, "methodToExpect");
+ prepareForStubbing(mock);
+ Whitebox.invokeMethod(mock, methodToExpect, arguments);
+ }
+
+ @Override
+ public <T> void when(Class<T> classMock, Object... arguments) throws Exception {
+ assertNotNull(classMock, "classMock");
+ when(classMock);
+ Whitebox.invokeMethod(classMock, arguments);
+ }
+
+ @Override
+ public <T> void when(Class<T> classMock, String methodToExpect, Object... parameters) throws Exception {
+ assertNotNull(classMock, "classMock");
+ assertNotNull(methodToExpect, "methodToExpect");
+ when(classMock);
+ Whitebox.invokeMethod(classMock, methodToExpect, parameters);
+ }
+
+ @Override
+ public <T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception {
+ assertNotNull(classMock, "classMock");
+ assertNotNull(method, "Method");
+ when(classMock);
+ return new DefaultPrivatelyExpectedArguments(classMock, method);
+ }
+
+ private void assertNotNull(Object object, String name) {
+ if (object == null) {
+ throw new IllegalArgumentException(name + " cannot be null");
+ }
+ }
+
+ private <T> void prepareForStubbing(T mock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository.getInstanceMethodInvocationControl(mock);
+ addAnswersForStubbing(invocationControl);
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java
new file mode 100644
index 0000000..57e56b9
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.Whitebox;
+
+import java.util.regex.Matcher;
+
+public class InvocationControlAssertionError {
+ private static final String AT = "at";
+ private static final String ERROR_LOCATION_MARKER = "->";
+ private static final String COLON_NEWLINE = ":\n";
+ private static final String HERE_TEXT = "here:\n";
+ private static final String UNDESIRED_INVOCATION_TEXT = " Undesired invocation:";
+
+ public static void updateErrorMessageForVerifyNoMoreInteractions(AssertionError errorToUpdate) {
+ /*
+ * VerifyNoMoreInteractions failed, we need to update the error message.
+ */
+ String verifyNoMoreInteractionsInvocation = null;
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ for (int i = stackTrace.length - 1; i >= 0; i--) {
+ final StackTraceElement stackTraceElement = stackTrace[i];
+ if (stackTraceElement.getClassName().equals(PowerMockito.class.getName())
+ && stackTraceElement.getMethodName().equals("verifyNoMoreInteractions")) {
+ final int invocationStackTraceIndex;
+ if (stackTrace[i + 1].getClassName().equals(PowerMockito.class.getName())
+ && stackTrace[i + 1].getMethodName().equals("verifyZeroInteractions")) {
+ invocationStackTraceIndex = i + 2;
+ } else {
+ invocationStackTraceIndex = i + 1;
+ }
+ verifyNoMoreInteractionsInvocation = stackTrace[invocationStackTraceIndex].toString();
+ }
+ }
+
+ if (verifyNoMoreInteractionsInvocation == null) {
+ // Something unexpected happened, just return
+ return;
+ }
+ String message = errorToUpdate.getMessage();
+ StringBuilder builder = new StringBuilder();
+ builder.append(message);
+ final int indexOfFirstAt = message.indexOf(AT);
+ final int startOfVerifyNoMoreInteractionsInvocation = indexOfFirstAt + AT.length() + 1;
+ final int endOfVerifyNoMoreInteractionsInvocation = message.indexOf('\n', indexOfFirstAt + AT.length());
+ builder.replace(startOfVerifyNoMoreInteractionsInvocation, endOfVerifyNoMoreInteractionsInvocation,
+ verifyNoMoreInteractionsInvocation);
+ builder.delete(builder.indexOf("\n", endOfVerifyNoMoreInteractionsInvocation + 1), builder.lastIndexOf("\n"));
+ Whitebox.setInternalState(errorToUpdate, builder.toString());
+ }
+
+ public static void updateErrorMessageForMethodInvocation(AssertionError errorToUpdate) {
+ /*
+ * We failed to verify the new substitution mock. This happens when, for
+ * example, the user has done something like
+ * whenNew(MyClass.class).thenReturn(myMock).times(3) when in fact an
+ * instance of MyClass has been created less or more times than 3.
+ */
+ Whitebox.setInternalState(errorToUpdate, "\n" + changeMessageContent(errorToUpdate.getMessage()));
+ }
+
+ public static void throwAssertionErrorForNewSubstitutionFailure(AssertionError oldError, Class<?> type) {
+ /*
+ * We failed to verify the new substitution mock. This happens when, for
+ * example, the user has done something like
+ * whenNew(MyClass.class).thenReturn(myMock).times(3) when in fact an
+ * instance of MyClass has been created less or more times than 3.
+ */
+ final String newSubsitutionClassName = InvocationSubstitute.class.getSimpleName();
+ final String newSubsitutionClassNameInMockito = newSubsitutionClassName.substring(0, 1).toLowerCase()
+ + newSubsitutionClassName.substring(1);
+ String message = oldError.getMessage();
+ final String newSubsitutionMethodName = InvocationSubstitute.class.getDeclaredMethods()[0].getName();
+ message = message.replaceAll(newSubsitutionClassNameInMockito + "." + newSubsitutionMethodName, Matcher
+ .quoteReplacement(type.getName()));
+ message = message.replaceAll("method", "constructor");
+ throw new AssertionError(changeMessageContent(message));
+ }
+
+ private static String changeMessageContent(String message) {
+ /*
+ * Temp fix: Remove powermock internal "at locations" (points to which
+ * line the expectation went wrong in Mockito). We should try to find
+ * the real ones instead
+ */
+ StringBuilder builder = removeFailureLocations(message);
+ // Remove "Undesired invocation:"
+ removeText(builder, UNDESIRED_INVOCATION_TEXT);
+
+ removeAndReplaceText(builder, HERE_TEXT, ' ');
+
+ removeAndReplaceText(builder, COLON_NEWLINE, ' ');
+ final String finalMessage = builder.toString().trim();
+ return finalMessage;
+ }
+
+ private static StringBuilder removeFailureLocations(String message) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(message);
+ int indexOfBeginLocation = builder.indexOf(ERROR_LOCATION_MARKER);
+ while (indexOfBeginLocation > 0) {
+ int indexOfLocationEnd = builder.indexOf("\n", indexOfBeginLocation);
+ builder.delete(indexOfBeginLocation, indexOfLocationEnd < 0 ? builder.length() : indexOfLocationEnd + 1);
+ indexOfBeginLocation = builder.indexOf(ERROR_LOCATION_MARKER);
+ }
+ return builder;
+ }
+
+ private static void removeAndReplaceText(StringBuilder builder, String text, char appender) {
+ int currentTextIndex = builder.indexOf(text);
+ int previousTextIndex = 0;
+ boolean isSingleConcat = true;
+ while (currentTextIndex > 0) {
+ previousTextIndex = currentTextIndex;
+ builder.delete(currentTextIndex, currentTextIndex + text.length());
+ currentTextIndex = builder.indexOf(text);
+ if (isLastFinding(currentTextIndex) && !isSingleConcat) {
+ builder.replace(builder.length(), builder.length(), ".");
+ } else {
+ builder.replace(previousTextIndex, previousTextIndex + 1, String.valueOf(
+ builder.charAt(previousTextIndex)).toLowerCase());
+ builder.insert(previousTextIndex, String.valueOf(appender));
+ currentTextIndex++;
+ isSingleConcat = false;
+ }
+ }
+ }
+
+ private static boolean isLastFinding(int index) {
+ return index < 0;
+ }
+
+ private static void removeText(StringBuilder builder, String text) {
+ int textIndex = builder.indexOf(text);
+ while (textIndex > 0) {
+ builder.delete(textIndex, textIndex + text.length());
+ textIndex = builder.indexOf(text);
+ }
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java
new file mode 100644
index 0000000..15c8bb8
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java
@@ -0,0 +1,338 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.debugging.Localized;
+import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.SequenceNumber;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.internal.verification.StaticMockAwareVerificationMode;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+import org.powermock.api.support.SafeExceptionRethrower;
+import org.powermock.core.MockGateway;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A Mockito implementation of the {@link MethodInvocationControl} interface.
+ */
+public class MockitoMethodInvocationControl implements MethodInvocationControl {
+
+ private final MethodInterceptorFilter methodInterceptorFilter;
+
+ private final Set<Method> mockedMethods;
+ private final Object delegator;
+ private final Object mockInstance;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param methodInterceptionFilter
+ * The methodInterceptionFilter to be associated with this
+ * instance.
+ * @param mockInstance
+ * The actual mock instance. May be <code>null</code>. Even
+ * though the mock instance may not be used it's needed to keep a
+ * reference to this object otherwise it may be garbage collected
+ * in some situations. For example when mocking static methods we
+ * don't return the mock object and thus it will be garbage
+ * collected (and thus the finalize method will be invoked which
+ * will be caught by the proxy and the test will fail because we
+ * haven't setup expectations for this method) because then that
+ * object has no reference. In order to avoid this we keep a
+ * reference to this instance here.
+ * @param methodsToMock
+ * The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null or empty, all methods for
+ * the <code>invocationHandler</code> are considered to be
+ * mocked.
+ */
+ public MockitoMethodInvocationControl(MethodInterceptorFilter methodInterceptionFilter, Object mockInstance, Method... methodsToMock) {
+ this(methodInterceptionFilter, null, mockInstance, methodsToMock);
+ }
+
+ /**
+ * Creates a new instance with a delegator. This delegator may be
+ * <code>null</code> (if it is then no calls will be forwarded to this
+ * instance). If a delegator exists (i.e. not null) all non-mocked calls
+ * will be delegated to that instance.
+ * @param methodInterceptionFilter
+ * The methodInterceptionFilter to be associated with this
+ * instance.
+ * @param delegator
+ * If the user spies on an instance the original instance must be
+ * injected here.
+ * @param mockInstance
+ * The actual mock instance. May be <code>null</code>. Even
+ * though the mock instance may not be used it's needed to keep a
+ * reference to this object otherwise it may be garbage collected
+ * in some situations. For example when mocking static methods we
+ * don't return the mock object and thus it will be garbage
+ * collected (and thus the finalize method will be invoked which
+ * will be caught by the proxy and the test will fail because we
+ * haven't setup expectations for this method) because then that
+ * object has no reference. In order to avoid this we keep a
+ * reference to this instance here.
+ * @param methodsToMock
+ * The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null or empty, all methods for
+ * the <code>invocationHandler</code> are considered to be
+ */
+ public MockitoMethodInvocationControl(MethodInterceptorFilter methodInterceptionFilter, Object delegator,
+ Object mockInstance, Method... methodsToMock) {
+ if (methodInterceptionFilter == null) {
+ throw new IllegalArgumentException("Invocation Handler cannot be null.");
+ }
+
+ this.mockedMethods = toSet(methodsToMock);
+ this.mockInstance = mockInstance;
+ this.delegator = delegator;
+ this.methodInterceptorFilter = methodInterceptionFilter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isMocked(Method method) {
+ return mockedMethods == null || (mockedMethods != null && mockedMethods.contains(method));
+ }
+
+ private boolean isInVerificationMode() {
+ return getVerificationMode() != null;
+ }
+
+ private VerificationMode getVerificationMode() {
+ try {
+ MockingProgress progress = (MockingProgress) Whitebox.invokeMethod(ThreadSafeMockingProgress.class,
+ "threadSafely");
+ return getVerificationModeFromMockProgress(progress);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private VerificationMode getVerificationModeFromMockProgress(MockingProgress mockingProgress) {
+ if (mockingProgress == null) {
+ return null;
+ }
+ if (mockingProgress instanceof ThreadSafeMockingProgress) {
+ ThreadLocal<MockingProgress> threadLocal = Whitebox.getInternalState(mockingProgress, ThreadLocal.class);
+ return getVerificationModeFromMockProgress(threadLocal.get());
+ } else {
+ Localized<VerificationMode> verificationMode = Whitebox.getInternalState(mockingProgress, Localized.class);
+ return verificationMode == null ? null : verificationMode.getObject();
+ }
+ }
+
+ @Override
+ public Object invoke(final Object obj, final Method method, final Object[] arguments) throws Throwable {
+ /*
+ * If we come here and it means that the class has been modified by
+ * PowerMock. If this handler has a delegator (i.e. is in spy mode in
+ * the current implementation) and it has been caught by the Mockito
+ * proxy before our Mockgateway we need to know if the method is private
+ * or not. Because if the previously described preconditions are met and
+ * the method is not private it means that Mockito has already processed
+ * the method invocation and we should NOT delegate the call to Mockito
+ * again (thus we return proceed). If we would do that Mockito will
+ * receive multiple method invocations to proxy for each method
+ * invocation. For privately spied methods Mockito haven't received the
+ * invocation and thus we should delegate the call to the Mockito proxy.
+ */
+ final Object returnValue;
+ final int methodModifiers = method.getModifiers();
+ if (hasDelegator() && !Modifier.isPrivate(methodModifiers) && !Modifier.isFinal(methodModifiers)
+ && !Modifier.isStatic(methodModifiers) && hasBeenCaughtByMockitoProxy()) {
+ returnValue = MockGateway.PROCEED;
+ } else {
+ boolean inVerificationMode = isInVerificationMode();
+ if (WhiteboxImpl.isClass(obj) && inVerificationMode) {
+ handleStaticVerification((Class<?>) obj);
+ }
+ returnValue = performIntercept(methodInterceptorFilter, obj, method, arguments);
+ if (returnValue == null) {
+ return MockGateway.SUPPRESS;
+ }
+ }
+ return returnValue;
+ }
+
+ private void handleStaticVerification(Class<?> cls) {
+ VerificationMode verificationMode = getVerificationMode();
+ if (verificationMode instanceof StaticMockAwareVerificationMode) {
+ ((StaticMockAwareVerificationMode) verificationMode).setClassMock(cls);
+ }
+ }
+
+ private boolean hasBeenCaughtByMockitoProxy() {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ StackTraceFilter filter = new StackTraceFilter();
+ /*
+ * We filter the stack-trace to check if "Mockito" exists as a stack trace element. (The filter method
+ * remove all Mocktio stack trace elements). If the filtered stack trace length is not equal to the original stack trace length
+ * this means that the call has been caught by Mockito.
+ */
+ final StackTraceElement[] filteredStackTrace = filter.filter(stackTrace, true);
+ return filteredStackTrace.length != stackTrace.length;
+ }
+
+ private Object performIntercept(MethodInterceptorFilter invocationHandler, final Object interceptionObject,
+ final Method method, Object[] arguments) throws Throwable {
+ MockHandler mockHandler = invocationHandler.getHandler();
+
+ final CleanTraceRealMethod cglibProxyRealMethod = new CleanTraceRealMethod(new RealMethod() {
+ private static final long serialVersionUID = 4564320968038564170L;
+
+ @Override
+ public Object invoke(Object target, Object[] arguments) throws Throwable {
+ /*
+ * Instruct the MockGateway to don't intercept the next call.
+ * The reason is that when Mockito is spying on objects it
+ * should call the "real method" (which is proxied by Mockito
+ * anyways) so that we don't end up in here one more time which
+ * causes infinite recursion. This should not be done if the
+ * interceptionObject is a final system class because these are
+ * never caught by the Mockito proxy.
+ */
+ final Class<?> type = Whitebox.getType(interceptionObject);
+ final boolean isFinalSystemClass = type.getName().startsWith("java.") && Modifier.isFinal(type.getModifiers());
+ if (!isFinalSystemClass) {
+ MockRepository.putAdditionalState(MockGateway.DONT_MOCK_NEXT_CALL, true);
+ }
+ try {
+ return method.invoke(target, arguments);
+ } catch (InvocationTargetException e) {
+ SafeExceptionRethrower.safeRethrow(e.getCause());
+ }
+ return null;
+ }
+ });
+
+ Invocation invocation = new InvocationImpl(
+ interceptionObject,
+ new DelegatingMethod(method),
+ arguments,
+ SequenceNumber.next(),
+ cglibProxyRealMethod) {
+ private static final long serialVersionUID = -3679957412502758558L;
+
+ @Override
+ public String toString() {
+ return new ToStringGenerator().generate(getMock(), getMethod(), getArguments());
+ }
+ };
+
+ try {
+ return replaceMatchersBinderIfNeeded(mockHandler).handle(invocation);
+ } catch (NotAMockException e) {
+ if(invocation.getMock().getClass().getName().startsWith("java.") && MockRepository.getInstanceMethodInvocationControl(invocation.getMock()) != null) {
+ return invocation.callRealMethod();
+ } else {
+ throw e;
+ }
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForMethodInvocation(e);
+ throw e;
+ }
+ }
+
+ private MockHandler replaceMatchersBinderIfNeeded(MockHandler mockHandler) {
+ if(!Whitebox.getFieldsOfType(mockHandler, MatchersBinder.class).isEmpty()) {
+ Whitebox.setInternalState(mockHandler, new PowerMockMatchersBinder());
+ } else if(!Whitebox.getFieldsOfType(mockHandler, InternalMockHandler.class).isEmpty()) {
+ final MockHandler internalMockHandler = Whitebox.getInternalState(mockHandler, MockHandler.class);
+ return replaceMatchersBinderIfNeeded(internalMockHandler);
+ }
+ return mockHandler;
+ }
+
+ @Override
+ public Object replay(Object... mocks) {
+ throw new IllegalStateException("Internal error: No such thing as replay exists in Mockito.");
+ }
+
+ @Override
+ public Object reset(Object... mocks) {
+ throw new IllegalStateException("Internal error: No such thing as reset exists in Mockito.");
+ }
+
+ @Override
+ public Object verify(Object... mocks) {
+ if (mocks == null || mocks.length != 1) {
+ throw new IllegalArgumentException("Must supply one mock to the verify method.");
+ }
+ return Mockito.verify(mocks[0]);
+ }
+
+ public void verifyNoMoreInteractions() {
+ try {
+ final MockHandler mockHandler = methodInterceptorFilter.getHandler();
+ if (mockHandler instanceof MockHandler) {
+ InvocationContainer invocationContainer = Whitebox.<InvocationContainer>invokeMethod(mockHandler, "getInvocationContainer");
+ VerificationDataImpl data = new VerificationDataImpl(invocationContainer, null);
+ VerificationModeFactory.noMoreInteractions().verify(data);
+ } else {
+ throw new RuntimeException(
+ "Cannot perform verifyNoMoreInteractions because of unknown mockhandler type "
+ + mockHandler.getClass());
+ }
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForVerifyNoMoreInteractions(e);
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error",e);
+ }
+ }
+
+ private Set<Method> toSet(Method... methods) {
+ return methods == null ? null : new HashSet<Method>(Arrays.asList(methods));
+ }
+
+ private boolean hasDelegator() {
+ return delegator != null;
+ }
+
+ public MethodInterceptorFilter getInvocationHandler() {
+ return methodInterceptorFilter;
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java
new file mode 100644
index 0000000..001b3e9
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.verification.VerificationMode;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+
+import static org.mockito.Mockito.times;
+
+public class MockitoNewInvocationControl<T> implements NewInvocationControl<OngoingStubbing<T>> {
+ private final InvocationSubstitute<T> substitute;
+
+ public MockitoNewInvocationControl(InvocationSubstitute<T> substitute) {
+ if (substitute == null) {
+ throw new IllegalArgumentException("Internal error: substitute cannot be null.");
+ }
+ this.substitute = substitute;
+ }
+
+ @Override
+ public Object invoke(Class<?> type, Object[] args, Class<?>[] sig) throws Exception {
+ Constructor<?> constructor = WhiteboxImpl.getConstructor(type, sig);
+ if (constructor.isVarArgs()) {
+ Object varArgs = args[args.length - 1];
+ final int varArgsLength = Array.getLength(varArgs);
+ Object[] oldArgs = args;
+ args = new Object[args.length + varArgsLength - 1];
+ System.arraycopy(oldArgs, 0, args, 0, oldArgs.length - 1);
+ for (int i = oldArgs.length - 1, j=0; i < args.length; i++, j++) {
+ args[i] = Array.get(varArgs, j);
+ }
+ }
+ try {
+ return substitute.performSubstitutionLogic(args);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+
+ // Won't happen
+ return null;
+ }
+
+ @Override
+ public OngoingStubbing<T> expectSubstitutionLogic(Object... arguments) throws Exception {
+ return Mockito.when(substitute.performSubstitutionLogic(arguments));
+ }
+
+ public InvocationSubstitute<T> getSubstitute() {
+ return substitute;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object replay(Object... mocks) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object verify(Object... mocks) {
+ final VerificationMode verificationMode;
+ Object mode = MockRepository.getAdditionalState("VerificationMode");
+ if (mode != null) {
+ if (mode instanceof VerificationMode) {
+ verificationMode = (VerificationMode) mode;
+ } else {
+ throw new IllegalStateException("Internal error. VerificationMode in MockRepository was not of type "
+ + VerificationMode.class.getName() + ".");
+ }
+ } else {
+ verificationMode = times(1);
+ }
+ Mockito.verify(substitute, verificationMode);
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized Object reset(Object... mocks) {
+ Mockito.<InvocationSubstitute<T>> reset(substitute);
+ return null;
+ }
+
+ public void verifyNoMoreInteractions() {
+ try {
+ Mockito.verifyNoMoreInteractions(substitute);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForVerifyNoMoreInteractions(e);
+ throw e;
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java
new file mode 100644
index 0000000..e9bfb1d
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java
@@ -0,0 +1,42 @@
+package org.powermock.api.mockito.internal.invocation;
+
+import org.hamcrest.Matcher;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.progress.ArgumentMatcherStorage;
+import org.mockito.invocation.Invocation;
+
+import java.util.List;
+
+/**
+ * This class is essentially a copy of {@link org.mockito.internal.invocation.MatchersBinder} with the exception that
+ * the InvocationMatcher is replaced and its toString method is overwritten to avoid exceptions. For why these exceptions happen
+ * refer to ToStringGenerator in this package.
+ */
+public class PowerMockMatchersBinder extends MatchersBinder {
+
+ public InvocationMatcher bindMatchers(ArgumentMatcherStorage argumentMatcherStorage, final Invocation invocation) {
+ List<LocalizedMatcher> lastMatchers = argumentMatcherStorage.pullLocalizedMatchers();
+ validateMatchers(invocation, lastMatchers);
+
+ final InvocationMatcher invocationWithMatchers = new InvocationMatcher(invocation, (List<Matcher>)(List) lastMatchers) {
+ @Override
+ public String toString() {
+ return invocation.toString();
+ }
+ };
+ return invocationWithMatchers;
+ }
+
+ private void validateMatchers(Invocation invocation, List<LocalizedMatcher> lastMatchers) {
+ if (!lastMatchers.isEmpty()) {
+ int recordedMatchersSize = lastMatchers.size();
+ int expectedMatchersSize = invocation.getArguments().length;
+ if (expectedMatchersSize != recordedMatchersSize) {
+ new Reporter().invalidUseOfMatchers(expectedMatchersSize, lastMatchers);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java
new file mode 100644
index 0000000..56e40f4
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java
@@ -0,0 +1,44 @@
+package org.powermock.api.mockito.internal.invocation;
+
+import org.hamcrest.Matcher;
+import org.mockito.internal.invocation.ArgumentsProcessor;
+import org.mockito.internal.matchers.MatchersPrinter;
+import org.mockito.internal.reporting.PrintSettings;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * We need to override the toString() in some classes because normally the toString
+ * "method" is assembled by calling the "qualifiedName" method but
+ * this is not possible in our case. The reason is that the
+ * qualifiedName method does
+ *
+ * <pre>
+ * new MockUtil().getMockName(mock)
+ * </pre>
+ *
+ * which later will call the "isMockitoMock" method which will
+ * return false and an exception will be thrown. The reason why
+ * "isMockitoMock" returns false is that the mock is not created by
+ * the Mockito CGLib Enhancer in case of static methods.
+ */
+public class ToStringGenerator {
+
+ public String generate(Object mock, Method method, Object[] arguments) {
+ final List<Matcher> matcherList = ArgumentsProcessor.argumentsToMatchers(arguments);
+ final PrintSettings printSettings = new PrintSettings();
+ MatchersPrinter matchersPrinter = new MatchersPrinter();
+
+ String methodName = Whitebox.getType(mock).getName() + "." + method.getName();
+ String invocation = methodName + matchersPrinter.getArgumentsLine(matcherList, printSettings);
+ if (printSettings.isMultiline()
+ || (!matcherList.isEmpty() && invocation.length() > Whitebox.<Integer> getInternalState(
+ PrintSettings.class, "MAX_LINE_LENGTH"))) {
+ return methodName + matchersPrinter.getArgumentsBlock(matcherList, printSettings);
+ } else {
+ return invocation;
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java
new file mode 100644
index 0000000..75b1649
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.creation.instance.InstantiatorProvider;
+import org.mockito.internal.handler.MockHandlerFactory;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.api.mockito.repackaged.ClassImposterizer;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+import org.powermock.core.ClassReplicaCreator;
+import org.powermock.core.DefaultFieldValueGenerator;
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+ at SuppressWarnings("unchecked")
+public class MockCreator extends AbstractMockCreator {
+
+
+ private static final MockCreator MOCK_CREATOR = new MockCreator();
+
+ @SuppressWarnings("unchecked")
+ public static <T> T mock(Class<T> type, boolean isStatic, boolean isSpy, Object delegator,
+ MockSettings mockSettings, Method... methods) {
+ return MOCK_CREATOR.createMock(type, isStatic, isSpy, delegator, mockSettings, methods);
+ }
+
+ @Override
+ protected <T> T createMock(Class<T> type, boolean isStatic, boolean isSpy, Object delegator,
+ MockSettings mockSettings, Method... methods) {
+ if (type == null) {
+ throw new IllegalArgumentException("The class to mock cannot be null");
+ }
+
+ validateType(type, isStatic, isSpy);
+
+ final String mockName = toInstanceName(type, mockSettings);
+
+ MockRepository.addAfterMethodRunner(new MockitoStateCleanerRunnable());
+
+ final Class<T> typeToMock;
+ if (isFinalJavaSystemClass(type)) {
+ typeToMock = (Class<T>) new ClassReplicaCreator().createClassReplica(type);
+ } else {
+ typeToMock = type;
+ }
+
+ final MockData<T> mockData = createMethodInvocationControl(mockName, typeToMock, methods, isSpy, delegator,
+ mockSettings);
+
+ T mock = mockData.getMock();
+ if (isFinalJavaSystemClass(type) && !isStatic) {
+ mock = Whitebox.newInstance(type);
+ DefaultFieldValueGenerator.fillWithDefaultValues(mock);
+ }
+
+ if (isStatic) {
+ MockRepository.putStaticMethodInvocationControl(type, mockData.getMethodInvocationControl());
+ } else {
+ MockRepository.putInstanceMethodInvocationControl(mock, mockData.getMethodInvocationControl());
+ }
+
+ if (isSpy) {
+ new LenientCopyTool().copyToMock(delegator, mock);
+ }
+
+ return mock;
+ }
+
+ private <T> boolean isFinalJavaSystemClass(Class<T> type) {
+ return type.getName().startsWith("java.") && Modifier.isFinal(type.getModifiers());
+ }
+
+ private <T> MockData<T> createMethodInvocationControl(final String mockName, Class<T> type,
+ Method[] methods, boolean isSpy, Object delegator, MockSettings mockSettings) {
+ final MockSettingsImpl settings;
+ if (mockSettings == null) {
+ // We change the context classloader to the current CL in order for the Mockito
+ // framework to load it's plugins (such as MockMaker) correctly.
+ final ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(MockCreator.class.getClassLoader());
+ try {
+ settings = (MockSettingsImpl) Mockito.withSettings();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCL);
+ }
+ } else {
+ settings = (MockSettingsImpl) mockSettings;
+ }
+
+ if (isSpy) {
+ settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
+ }
+
+ settings.setMockName(new MockNameImpl(mockName));
+ settings.setTypeToMock(type);
+
+ InternalMockHandler mockHandler = new MockHandlerFactory().create(settings);
+ MethodInterceptorFilter filter = new PowerMockMethodInterceptorFilter(mockHandler, settings);
+ final T mock = new ClassImposterizer(new InstantiatorProvider().getInstantiator(settings)).imposterise(filter, type);
+ ClassLoader classLoader = mock.getClass().getClassLoader();
+ if (classLoader instanceof MockClassLoader) {
+ MockClassLoader mcl = (MockClassLoader) classLoader;
+ mcl.cache(mock.getClass());
+ }
+ final MockitoMethodInvocationControl invocationControl = new MockitoMethodInvocationControl(
+ filter,
+ isSpy && delegator == null ? new Object() : delegator,
+ mock,
+ methods);
+
+ return new MockData<T>(invocationControl, mock);
+ }
+
+ private String toInstanceName(Class<?> clazz, final MockSettings mockSettings) {
+ // if the settings define a mock name, use it
+ if (mockSettings instanceof MockSettingsImpl<?>) {
+ String settingName = ((MockSettingsImpl<?>) mockSettings).getName();
+ if (settingName != null) {
+ return settingName;
+ }
+ }
+
+ // else, use the class name as mock name
+ String className = clazz.getSimpleName();
+ if (className.length() == 0) {
+ return clazz.getName();
+ }
+ // lower case first letter
+ return className.substring(0, 1).toLowerCase() + className.substring(1);
+ }
+
+ /**
+ * Class that encapsulate a mock and its corresponding invocation control.
+ */
+ private class MockData<T> {
+ private final MockitoMethodInvocationControl methodInvocationControl;
+
+ private final T mock;
+
+ MockData(MockitoMethodInvocationControl methodInvocationControl, T mock) {
+ this.methodInvocationControl = methodInvocationControl;
+ this.mock = mock;
+ }
+
+ public MockitoMethodInvocationControl getMethodInvocationControl() {
+ return methodInvocationControl;
+ }
+
+ public T getMock() {
+ return mock;
+ }
+ }
+
+ /**
+ * Clear state in Mockito that retains memory between tests
+ */
+ private class MockitoStateCleanerRunnable implements Runnable {
+ public void run() {
+ MockitoStateCleaner cleaner = new MockitoStateCleaner();
+ cleaner.clearConfiguration();
+ cleaner.clearMockProgress();
+ }
+
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java
new file mode 100644
index 0000000..92648bb
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java
@@ -0,0 +1,30 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.powermock.api.support.ClassLoaderUtil;
+import org.powermock.reflect.Whitebox;
+
+class MockitoStateCleaner {
+
+ void clearMockProgress() {
+ clearThreadLocalIn(ThreadSafeMockingProgress.class);
+ }
+
+ void clearConfiguration() {
+ clearThreadLocalIn(GlobalConfiguration.class);
+ }
+
+ private void clearThreadLocalIn(Class<?> cls) {
+ Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
+ final Class<?> clazz;
+ if(ClassLoaderUtil.hasClass(cls, ClassLoader.getSystemClassLoader())) {
+ clazz = ClassLoaderUtil.loadClass(cls, ClassLoader.getSystemClassLoader());
+ } else {
+ clazz = ClassLoaderUtil.loadClass(cls, cls.getClassLoader());
+ }
+ Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
+ }
+
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java
new file mode 100644
index 0000000..0351449
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java
@@ -0,0 +1,29 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.cglib.proxy.MethodProxy;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+
+import java.lang.reflect.Method;
+
+class PowerMockMethodInterceptorFilter extends MethodInterceptorFilter {
+
+ public PowerMockMethodInterceptorFilter(InternalMockHandler handler,
+ MockCreationSettings mockSettings) {
+ super(handler, mockSettings);
+ }
+
+ @Override
+ public Object intercept(Object proxy, Method method, Object[] args,
+ MethodProxy methodProxy) throws Throwable {
+ Object intercept = super.intercept(proxy, method, args, methodProxy);
+ if ("finalize".equals(method.getName())) {
+ MockitoStateCleaner cleaner = new MockitoStateCleaner();
+ cleaner.clearConfiguration();
+ cleaner.clearMockProgress();
+ }
+ return intercept;
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java
new file mode 100644
index 0000000..47e53ac
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.mockmaker;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+import org.powermock.api.mockito.repackaged.CglibMockMaker;
+import org.powermock.core.classloader.MockClassLoader;
+
+import java.util.List;
+
+/**
+ * A PowerMock implementation of the MockMaker. Right now it simply delegates to the default Mockito
+ * {@link org.mockito.plugins.MockMaker} via {@link org.mockito.internal.configuration.plugins.Plugins#getMockMaker()}
+ * but in the future we may use it more properly.
+ * The reason for its existence is that the current Mockito MockMaker throws exception when getting the name
+ * from of a mock that is created by PowerMock but not know for Mockito. This is triggered when by the
+ * {@link org.mockito.internal.util.MockUtil} class.
+ * For more details see the {@link org.powermock.api.mockito.internal.invocation.ToStringGenerator}.
+ */
+public class PowerMockMaker implements MockMaker {
+ private final MockMaker cglibMockMaker = new CglibMockMaker();
+
+ @Override
+ public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+ T mock = cglibMockMaker.createMock(settings, handler);
+ ClassLoader classLoader = cglibMockMaker.getClass().getClassLoader();
+ if (classLoader instanceof MockClassLoader) {
+ MockClassLoader mcl = (MockClassLoader) classLoader;
+ // The generated class is not picked up by PowerMock so we cache it here
+ mcl.cache(mock.getClass());
+ }
+ return mock;
+ }
+
+ @Override
+ public MockHandler getHandler(Object mock) {
+ // Return a fake mock handler for static method mocks
+ if (mock instanceof Class) {
+ return new PowerMockInternalMockHandler((Class<?>) mock);
+ } else {
+ return cglibMockMaker.getHandler(mock);
+ }
+ }
+
+ @Override
+ public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+ cglibMockMaker.resetMock(mock, newHandler, settings);
+ }
+
+ /**
+ * It needs to extend InternalMockHandler because Mockito requires the type to be of InternalMockHandler and not MockHandler
+ */
+ private static class PowerMockInternalMockHandler implements InternalMockHandler<Object> {
+ private final Class<?> mock;
+
+ public PowerMockInternalMockHandler(Class<?> mock) {
+ this.mock = mock;
+ }
+
+ @Override
+ public MockCreationSettings getMockSettings() {
+ final MockSettingsImpl mockSettings = new MockSettingsImpl();
+ mockSettings.setMockName(new MockNameImpl(mock.getName()));
+ mockSettings.setTypeToMock(mock);
+ return mockSettings;
+ }
+
+ @Override
+ public VoidMethodStubbable<Object> voidMethodStubbable(Object mock) {
+ return null;
+ }
+
+ @Override
+ public void setAnswersForStubbing(List<Answer> answers) {
+ }
+
+ @Override
+ public InvocationContainer getInvocationContainer() {
+ return null;
+ }
+
+ @Override
+ public Object handle(Invocation invocation) throws Throwable {
+ return null;
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java
new file mode 100644
index 0000000..842760b
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java
@@ -0,0 +1,39 @@
+package org.powermock.api.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.stubbing.answers.ReturnsElementsOf;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created by gauee on 12/11/15.
+ */
+public class ChainReturns implements Answer<Object> {
+ private final ReturnsElementsOf returnsElementsOf;
+
+ public ChainReturns(Object toBeReturn, Object... toBeReturnedOthers) {
+ List<Object> elements = new LinkedList<Object>();
+ elements.add(toBeReturn);
+ addOtherElementToBeReturned(elements, toBeReturnedOthers);
+
+ this.returnsElementsOf = new ReturnsElementsOf(elements);
+
+ }
+
+ private void addOtherElementToBeReturned(List<Object> elements, Object[] toBeReturnedOthers) {
+ if (toBeReturnedOthers == null) {
+ elements.add(toBeReturnedOthers);
+ return;
+ }
+ for (Object toBeReturnedOther : toBeReturnedOthers) {
+ elements.add(toBeReturnedOther);
+ }
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+ return returnsElementsOf.answer(invocationOnMock);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java
new file mode 100644
index 0000000..fa51d43
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.powermock.api.mockito.internal.invocation.InvocationControlAssertionError;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.api.mockito.verification.ConstructorArgumentsVerification;
+import org.powermock.core.spi.NewInvocationControl;
+
+public class DefaultConstructorArgumentsVerfication<T> implements ConstructorArgumentsVerification {
+
+ private final MockitoNewInvocationControl<T> invocationControl;
+ private final Class<?> type;
+
+ @SuppressWarnings("unchecked")
+ public DefaultConstructorArgumentsVerfication(NewInvocationControl<T> invocationControl, Class<?> type) {
+ this.type = type;
+ this.invocationControl = (MockitoNewInvocationControl<T>) invocationControl;
+ }
+
+ @Override
+ public void withArguments(Object argument, Object... arguments) throws Exception {
+ final Object[] realArguments;
+ if (arguments == null) {
+ realArguments = new Object[]{argument, null};
+ } else {
+ realArguments = new Object[arguments.length + 1];
+ realArguments[0] = argument;
+ System.arraycopy(arguments, 0, realArguments, 1, arguments.length);
+ }
+ invokeSubstitute(realArguments);
+ }
+
+ private void invokeSubstitute(Object... arguments) throws Exception {
+ try {
+ invocationControl.getSubstitute().performSubstitutionLogic(arguments);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+ }
+
+ @Override
+ public void withNoArguments() throws Exception {
+ invokeSubstitute(new Object[0]);
+ }
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java
new file mode 100644
index 0000000..051e37c
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.powermock.api.mockito.verification.PrivateMethodVerification;
+import org.powermock.api.mockito.verification.WithOrWithoutVerifiedArguments;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.impl.ArrayMergerImpl;
+
+import java.lang.reflect.Method;
+
+public class DefaultPrivateMethodVerification implements PrivateMethodVerification {
+
+ private final Object objectToVerify;
+
+ public DefaultPrivateMethodVerification(Object objectToVerify) {
+ this.objectToVerify = objectToVerify;
+ }
+
+ @Override
+ public void invoke(Object... arguments) throws Exception {
+ Whitebox.invokeMethod(objectToVerify, arguments);
+
+ }
+
+ @Override
+ public void invoke(String methodToExecute, Object... arguments) throws Exception {
+ Whitebox.invokeMethod(objectToVerify, methodToExecute, (Object[]) arguments);
+ }
+
+ @Override
+ public WithOrWithoutVerifiedArguments invoke(Method method) throws Exception {
+ return new VerificationArguments(method);
+ }
+
+ private class VerificationArguments implements WithOrWithoutVerifiedArguments {
+ private final Method method;
+
+ public VerificationArguments(Method method) {
+ if (method == null) {
+ throw new IllegalArgumentException("method cannot be null");
+ }
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ @Override
+ public void withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ method.invoke(objectToVerify, firstArgument);
+ } else {
+ Object[] arguments = new ArrayMergerImpl().mergeArrays(Object.class, new Object[]{firstArgument}, additionalArguments);
+ method.invoke(objectToVerify, arguments);
+ }
+ }
+
+ @Override
+ public void withNoArguments() throws Exception {
+ method.invoke(objectToVerify);
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java
new file mode 100644
index 0000000..17391c1
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.MockHandler;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * A custom extension of {@link MockAwareVerificationMode} for static method
+ * verification. The reason for this implementation is that since Mockito 1.8.4
+ * the verification code in Mockito
+ * {@link MockHandler#handle(org.mockito.internal.invocation.Invocation)} has
+ * changed and the verification mode MUST be an instance of
+ * {@link MockAwareVerificationMode} for the verification to work. Since
+ * verifying static methods is a two step process in PowerMock we need to be
+ * able to specify the class a later state then verification start. I.e. in
+ * standard Mockito they always know the mock object when doing verify before
+ * calling the method to verify:
+ *
+ * <pre>
+ * verify(mock).methodToVerify();
+ * </pre>
+ *
+ * In PowerMock we don't know the class when calling verifyStatic().
+ */
+public class StaticMockAwareVerificationMode extends MockAwareVerificationMode {
+
+ private Class<?> clsMock;
+
+ public StaticMockAwareVerificationMode(VerificationMode mode) {
+ super(null, mode);
+ }
+
+ public void setClassMock(Class<?> clsMock) {
+ this.clsMock = clsMock;
+ }
+
+ @Override
+ public void verify(VerificationData data) {
+ super.verify(data);
+ }
+
+ @Override
+ public Object getMock() {
+ return clsMock;
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java
new file mode 100644
index 0000000..bd3e5b9
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.Mockito;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.core.MockRepository;
+
+/**
+ * Verifies no more interactions, delegates to Mockito if PowerMockito doesn't
+ * find a supplied mock.
+ */
+public class VerifyNoMoreInteractions {
+
+ public static void verifyNoMoreInteractions(Object... objects) {
+ for (Object mock : objects) {
+ if (mock instanceof Class<?>) {
+ verifyNoMoreInteractions((Class<?>) mock);
+ } else {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getInstanceMethodInvocationControl(mock);
+ if (invocationControl != null) {
+ invocationControl.verifyNoMoreInteractions();
+ } else {
+ /*
+ * Delegate to Mockito if we have no handler registered for
+ * this object.
+ */
+ Mockito.verifyNoMoreInteractions(mock);
+ }
+ }
+ }
+ }
+
+ private static void verifyNoMoreInteractions(Class<?>... types) {
+ for (Class<?> type : types) {
+ final MockitoMethodInvocationControl invocationHandler = (MockitoMethodInvocationControl) MockRepository
+ .getStaticMethodInvocationControl(type);
+ if (invocationHandler != null) {
+ invocationHandler.verifyNoMoreInteractions();
+ }
+ MockitoNewInvocationControl<?> newInvocationControl = (MockitoNewInvocationControl<?>) MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ newInvocationControl.verifyNoMoreInteractions();
+ }
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java b/api/mockito/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java
new file mode 100644
index 0000000..ebd5311
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java
@@ -0,0 +1,103 @@
+package org.powermock.api.mockito.mockpolicies;
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.mockito.Mockito;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.mockpolicies.support.LogPolicySupport;
+
+import java.lang.reflect.Method;
+
+/**
+ * Sfl4j mock policy that injects a Mockito-created mock to be returned on calls to getLogger factory methods.
+ * The implementation returns a single mock instance per thread but it doesn't return a different mock instance based
+ * on the actual value passed to getLogger. This limitation is acceptable in most real uses cases.
+ * <p/>
+ * Tests that want to do verifications on the mocked logger can do so by getting the mocked instance as production code
+ * does: {@link org.slf4j.LoggerFactory#getLogger(Class)}. However, it is critical that the mocked logger is
+ * reset after each test in order to avoid crosstalk between test cases.
+ * <p/>
+ *
+ * @author Alexandre Normand <alexandre.normand at gmail.com>
+ */
+public class Slf4jMockPolicy implements PowerMockPolicy {
+
+ private static final String LOGGER_FACTORY_CLASS_NAME = "org.slf4j.LoggerFactory";
+ private static final String LOGGER_FACTORY_METHOD_NAME = "getLogger";
+ private static final String FRAMEWORK_NAME = "sfl4j";
+ private static final String LOGGER_CLASS_NAME = "org.slf4j.Logger";
+
+ private static ThreadLocal<Object> threadLogger = new ThreadLocal<Object>();
+
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings mockPolicyClassLoadingSettings) {
+ mockPolicyClassLoadingSettings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(
+ LOGGER_FACTORY_CLASS_NAME,
+ "org.apache.log4j.Appender",
+ "org.apache.log4j.xml.DOMConfigurator");
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings mockPolicyInterceptionSettings) {
+ LogPolicySupport logPolicySupport = new LogPolicySupport();
+
+ Method[] loggerFactoryMethods = logPolicySupport.getLoggerMethods(LOGGER_FACTORY_CLASS_NAME,
+ LOGGER_FACTORY_METHOD_NAME, FRAMEWORK_NAME);
+
+ initializeMockForThread(logPolicySupport);
+
+ for (Method loggerFactoryMethod : loggerFactoryMethods) {
+ mockPolicyInterceptionSettings.stubMethod(loggerFactoryMethod, threadLogger.get());
+ }
+ }
+
+ private void initializeMockForThread(LogPolicySupport logPolicySupport) {
+ Class<?> loggerClass = getLoggerClass(logPolicySupport);
+
+ if (threadLogger.get() == null) {
+ /*
+ * When mocking with Mockito we need to change the context CL to the same CL that is loading Mockito
+ * otherwise the Mockito plugin mechanism will load the PowerMockMaker from the wrong classloader.
+ */
+ final ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
+ final ClassLoader classLoader = Mockito.class.getClassLoader();
+ Thread.currentThread().setContextClassLoader(classLoader);
+ final Object mock;
+ try {
+ mock = Mockito.mock(loggerClass);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCl);
+ }
+
+ threadLogger.set(mock);
+ }
+ }
+
+ private Class<?> getLoggerClass(LogPolicySupport logPolicySupport) {
+ Class<?> loggerType;
+ try {
+ loggerType = logPolicySupport.getType(LOGGER_CLASS_NAME, FRAMEWORK_NAME);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return loggerType;
+ }
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java b/api/mockito/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java
new file mode 100644
index 0000000..d279785
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.powermocklistener;
+
+/**
+ * Before each test method all fields annotated with {@link Mock},
+ * {@link org.mockito.Mock} or {@link Mock} have mock objects created for them
+ * and injected to the fields.
+ *
+ * @deprecated Test Runners uses an annotation enabling listener per default
+ * since version 1.3. You should just remove this listener.
+ */
+public class AnnotationEnabler extends org.powermock.api.extension.listener.AnnotationEnabler {
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java
new file mode 100644
index 0000000..39ff833
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java
@@ -0,0 +1,426 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoSerializationIssue;
+import org.mockito.internal.creation.instance.InstantiatorProvider;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.mock.SerializableMode;
+
+import java.io.*;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.mockito.internal.util.StringJoiner.join;
+
+/**
+ * This is responsible for serializing a mock, it is enabled if the mock is implementing
+ * {@link Serializable}.
+ *
+ * <p>
+ * The way it works is to enable serialization via the {@link #enableSerializationAcrossJVM(MockCreationSettings)},
+ * if the mock settings is set to be serializable it will add the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable}
+ * interface.
+ * This interface defines a the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable#writeReplace()}
+ * whose signature match the one that is looked by the standard Java serialization.
+ * </p>
+ *
+ * <p>
+ * Then in the {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter} of mockito, if the <code>writeReplace</code> method is called,
+ * it will use the custom implementation of this class {@link #writeReplace(Object)}. This method has a specific
+ * knowledge on how to serialize a mockito mock that is based on CGLIB.
+ * </p>
+ *
+ * <p><strong>Only one instance per mock! See {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter}</strong></p>
+ *
+ * TODO use a proper way to add the interface
+ * TODO offer a way to disable completely this behavior, or maybe enable this behavior only with a specific setting
+ * TODO check the class is mockable in the deserialization side
+ *
+ * @see org.mockito.internal.creation.cglib.CglibMockMaker
+ * @see org.mockito.internal.creation.cglib.MethodInterceptorFilter
+ * @author Brice Dutheil
+ * @since 1.10.0
+ */
+ at Incubating
+class AcrossJVMSerializationFeature implements Serializable {
+ private static final long serialVersionUID = 7411152578314420778L;
+ private static final String MOCKITO_PROXY_MARKER = "MockitoProxyMarker";
+ private boolean instanceLocalCurrentlySerializingFlag = false;
+ private final Lock mutex = new ReentrantLock();
+
+ public boolean isWriteReplace(Method method) {
+ return method.getReturnType() == Object.class
+ && method.getParameterTypes().length == 0
+ && method.getName().equals("writeReplace");
+ }
+
+
+ /**
+ * Custom implementation of the <code>writeReplace</code> method for serialization.
+ *
+ * Here's how it's working and why :
+ * <ol>
+ * <li>
+ * <p>When first entering in this method, it's because some is serializing the mock, with some code like :
+ * <pre class="code"><code class="java">
+ * objectOutputStream.writeObject(mock);
+ * </code></pre>
+ * So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and
+ * execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock.
+ * At this point, the code will return an
+ * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy}.</p>
+ * </li>
+ * <li>
+ * <p>Now, in the constructor
+ * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy#AcrossJVMMockSerializationProxy(Object)}
+ * the mock is being serialized in a custom way (using
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream}) to a
+ * byte array. So basically it means the code is performing double nested serialization of the passed
+ * <code>mockitoMock</code>.</p>
+ *
+ * <p>However the <code>ObjectOutputStream</code> will still detect the custom
+ * <code>writeReplace</code> and execute it.
+ * <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)}
+ * doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the
+ * written stream, <strong><code>writeReplace</code> is always called by
+ * <code>ObjectOutputStream</code></strong>.)</em></p>
+ *
+ * <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using
+ * a flag that marks the mock as already being replaced, and then shouldn't replace itself again.
+ * <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs
+ * to be protected against concurrent access, hence the reentrant lock.</p>
+ * </li>
+ * </ol>
+ *
+ *
+ * @param mockitoMock The Mockito mock to be serialized.
+ * @return A wrapper ({@link AcrossJVMMockSerializationProxy}) to be serialized by the calling ObjectOutputStream.
+ * @throws ObjectStreamException
+ */
+ public Object writeReplace(Object mockitoMock) throws ObjectStreamException {
+ try {
+ // reentrant lock for critical section. could it be improved ?
+ mutex.lock();
+ // mark started flag // per thread, not per instance
+ // temporary loosy hack to avoid stackoverflow
+ if(mockIsCurrentlyBeingReplaced()) {
+ return mockitoMock;
+ }
+ mockReplacementStarted();
+
+ return new AcrossJVMMockSerializationProxy(mockitoMock);
+ } catch (IOException ioe) {
+ MockUtil mockUtil = new MockUtil();
+ MockName mockName = mockUtil.getMockName(mockitoMock);
+ String mockedType = mockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName();
+ throw new MockitoSerializationIssue(join(
+ "The mock '" + mockName + "' of type '" + mockedType + "'",
+ "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :",
+ " " + ioe.getMessage()
+ ), ioe);
+ } finally {
+ // unmark
+ mockReplacementCompleted();
+ mutex.unlock();
+ }
+ }
+
+
+ private void mockReplacementCompleted() {
+ instanceLocalCurrentlySerializingFlag = false;
+ }
+
+
+ private void mockReplacementStarted() {
+ instanceLocalCurrentlySerializingFlag = true;
+ }
+
+
+ private boolean mockIsCurrentlyBeingReplaced() {
+ return instanceLocalCurrentlySerializingFlag;
+ }
+
+
+ /**
+ * Enable serialization serialization that will work across classloaders / and JVM.
+ *
+ * <p>Only enable if settings says the mock should be serializable. In this case add the
+ * {@link AcrossJVMMockitoMockSerializable} to the extra interface list.</p>
+ *
+ * @param settings Mock creation settings.
+ * @param <T> Type param to not be bothered by the generics
+ */
+ public <T> void enableSerializationAcrossJVM(MockCreationSettings<T> settings) {
+ if (settings.getSerializableMode() == SerializableMode.ACROSS_CLASSLOADERS) {
+ // havin faith that this set is modifiable
+ // TODO use a proper way to add the interface
+ settings.getExtraInterfaces().add(AcrossJVMMockitoMockSerializable.class);
+ }
+ }
+
+
+ /**
+ * This is the serialization proxy that will encapsulate the real mock data as a byte array.
+ *
+ * <p>When called in the constructor it will serialize the mock in a byte array using a
+ * custom {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream} that
+ * will annotate the mock class in the stream.
+ * Other information are used in this class in order to facilitate deserialization.
+ * </p>
+ *
+ * <p>Deserialization of the mock will be performed by the {@link #readResolve()} method via
+ * the custom {@link MockitoMockObjectInputStream} that will be in charge of creating the mock class.</p>
+ */
+ public static class AcrossJVMMockSerializationProxy implements Serializable {
+
+
+ private static final long serialVersionUID = -7600267929109286514L;
+ private final byte[] serializedMock;
+ private final Class typeToMock;
+ private final Set<Class> extraInterfaces;
+ /**
+ * Creates the wrapper that be used in the serialization stream.
+ *
+ * <p>Immediately serializes the Mockito mock using specifically crafted
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream},
+ * in a byte array.</p>
+ *
+ * @param mockitoMock The Mockito mock to serialize.
+ * @throws IOException
+ */
+ public AcrossJVMMockSerializationProxy(Object mockitoMock) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutputStream = new MockitoMockObjectOutputStream(out);
+
+ objectOutputStream.writeObject(mockitoMock);
+
+ objectOutputStream.close();
+ out.close();
+
+ MockCreationSettings mockSettings = new MockUtil().getMockSettings(mockitoMock);
+ this.serializedMock = out.toByteArray();
+ this.typeToMock = mockSettings.getTypeToMock();
+ this.extraInterfaces = mockSettings.getExtraInterfaces();
+ }
+
+ /**
+ * Resolves the proxy to a new deserialized instance of the Mockito mock.
+ *
+ * <p>Uses the custom crafted {@link MockitoMockObjectInputStream} to deserialize the mock.</p>
+ *
+ * @return A deserialized instance of the Mockito mock.
+ * @throws ObjectStreamException
+ */
+ private Object readResolve() throws ObjectStreamException {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(serializedMock);
+ ObjectInputStream objectInputStream = new MockitoMockObjectInputStream(bis, typeToMock, extraInterfaces);
+
+ Object deserializedMock = objectInputStream.readObject();
+
+ bis.close();
+ objectInputStream.close();
+
+ return deserializedMock;
+ } catch (IOException ioe) {
+ throw new MockitoSerializationIssue(join(
+ "Mockito mock cannot be deserialized to a mock of '" + typeToMock.getCanonicalName() + "'. The error was :",
+ " " + ioe.getMessage(),
+ "If you are unsure what is the reason of this exception, feel free to contact us on the mailing list."
+ ), ioe);
+ } catch (ClassNotFoundException cce) {
+ throw new MockitoSerializationIssue(join(
+ "A class couldn't be found while deserializing a Mockito mock, you should check your classpath. The error was :",
+ " " + cce.getMessage(),
+ "If you are still unsure what is the reason of this exception, feel free to contact us on the mailing list."
+ ), cce);
+ }
+ }
+ }
+
+
+ /**
+ * Special Mockito aware <code>ObjectInputStream</code> that will resolve the Mockito proxy class.
+ *
+ * <p>
+ * This specificaly crafted ObjectInoutStream has the most important role to resolve the Mockito generated
+ * class. It is doing so via the {@link #resolveClass(java.io.ObjectStreamClass)} which looks in the stream
+ * for a Mockito marker. If this marker is found it will try to resolve the mockito class otherwise it
+ * delegates class resolution to the default super behavior.
+ * The mirror method used for serializing the mock is
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream#annotateClass(Class)}.
+ * </p>
+ *
+ * <p>
+ * When this marker is found, {@link org.mockito.internal.creation.cglib.ClassImposterizer} methods are being used to create the mock class.
+ * <em>Note that behind the <code>ClassImposterizer</code> there is CGLIB and the
+ * {@link org.mockito.internal.creation.util.SearchingClassLoader} that will look if this enhanced class has
+ * already been created in an accessible classloader ; so basically this code trusts the ClassImposterizer
+ * code.</em>
+ * </p>
+ */
+ public static class MockitoMockObjectInputStream extends ObjectInputStream {
+ private final Class typeToMock;
+ private final Set<Class> extraInterfaces;
+
+ public MockitoMockObjectInputStream(InputStream in, Class typeToMock, Set<Class> extraInterfaces) throws IOException {
+ super(in) ;
+ this.typeToMock = typeToMock;
+ this.extraInterfaces = extraInterfaces;
+ enableResolveObject(true); // ensure resolving is enabled
+ }
+
+ /**
+ * Resolve the Mockito proxy class if it is marked as such.
+ *
+ * <p>Uses the fields {@link #typeToMock} and {@link #extraInterfaces} to
+ * create the Mockito proxy class as the <code>ObjectStreamClass</code>
+ * doesn't carry useful information for this purpose.</p>
+ *
+ * @param desc Description of the class in the stream, not used.
+ * @return The class that will be used to deserialize the instance mock.
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ if (notMarkedAsAMockitoMock(readObject())) {
+ return super.resolveClass(desc);
+ }
+
+ // TODO check the class is mockable in the deserialization side
+ // ClassImposterizer.INSTANCE.canImposterise(typeToMock);
+
+ // create the Mockito mock class before it can even be deserialized
+ //TODO SF unify creation of imposterizer, constructor code duplicated, pulling in CreationSettings internal class
+ ClassImposterizer imposterizer = new ClassImposterizer(new InstantiatorProvider().getInstantiator(new CreationSettings()));
+ imposterizer.setConstructorsAccessible(typeToMock, true);
+ Class<?> proxyClass = imposterizer.createProxyClass(
+ typeToMock,
+ extraInterfaces.toArray(new Class[extraInterfaces.size()])
+ );
+
+ hackClassNameToMatchNewlyCreatedClass(desc, proxyClass);
+
+ return proxyClass;
+
+ }
+
+ /**
+ * Hack the <code>name</code> field of the given <code>ObjectStreamClass</code> with
+ * the <code>newProxyClass</code>.
+ *
+ * The parent ObjectInputStream will check the name of the class in the stream matches the name of the one
+ * that is created in this method.
+ *
+ * The CGLIB classes uses a hash of the classloader and/or maybe some other data that allow them to be
+ * relatively unique in a JVM.
+ *
+ * When names differ, which happens when the mock is deserialized in another ClassLoader, a
+ * <code>java.io.InvalidObjectException</code> is thrown, so this part of the code is hacking through
+ * the given <code>ObjectStreamClass</code> to change the name with the newly created class.
+ *
+ * @param descInstance The <code>ObjectStreamClass</code> that will be hacked.
+ * @param proxyClass The proxy class whose name will be applied.
+ * @throws InvalidObjectException
+ */
+ private void hackClassNameToMatchNewlyCreatedClass(ObjectStreamClass descInstance, Class<?> proxyClass) throws ObjectStreamException {
+ try {
+ Field classNameField = descInstance.getClass().getDeclaredField("name");
+ new FieldSetter(descInstance, classNameField).set(proxyClass.getCanonicalName());
+ } catch (NoSuchFieldException nsfe) {
+ // TODO use our own mockito mock serialization exception
+ throw new MockitoSerializationIssue(join(
+ "Wow, the class 'ObjectStreamClass' in the JDK don't have the field 'name',",
+ "this is definitely a bug in our code as it means the JDK team changed a few internal things.",
+ "",
+ "Please report an issue with the JDK used, a code sample and a link to download the JDK would be welcome."
+ ), nsfe);
+ }
+ }
+
+ /**
+ * Read the stream class annotation and identify it as a Mockito mock or not.
+ *
+ * @param marker The marker to identify.
+ * @return <code>true</code> if not marked as a Mockito, <code>false</code> if the class annotation marks a Mockito mock.
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ private boolean notMarkedAsAMockitoMock(Object marker) throws IOException, ClassNotFoundException {
+ return !MOCKITO_PROXY_MARKER.equals(marker);
+ }
+ }
+
+
+ /**
+ * Special Mockito aware <code>ObjectOutputStream</code>.
+ *
+ * <p>
+ * This output stream has the role of marking in the stream the Mockito class. This
+ * marking process is necessary to identify the proxy class that will need to be recreated.
+ *
+ * The mirror method used for deserializing the mock is
+ * {@link MockitoMockObjectInputStream#resolveClass(ObjectStreamClass)}.
+ * </p>
+ *
+ */
+ private static class MockitoMockObjectOutputStream extends ObjectOutputStream {
+ private static final String NOTHING = "";
+
+ public MockitoMockObjectOutputStream(ByteArrayOutputStream out) throws IOException {
+ super(out);
+ }
+
+ /**
+ * Annotates (marks) the class if this class is a Mockito mock.
+ *
+ * @param cl The class to annotate.
+ * @throws IOException
+ */
+ @Override
+ protected void annotateClass(Class<?> cl) throws IOException {
+ writeObject(mockitoProxyClassMarker(cl));
+ // might be also useful later, for embedding classloader info ...maybe ...maybe not
+ }
+
+ /**
+ * Returns the Mockito marker if this class is a Mockito mock.
+ *
+ * @param cl The class to mark.
+ * @return The marker if this is a Mockito proxy class, otherwise returns a void marker.
+ */
+ private String mockitoProxyClassMarker(Class<?> cl) {
+ if (AcrossJVMMockitoMockSerializable.class.isAssignableFrom(cl)) {
+ return MOCKITO_PROXY_MARKER;
+ } else {
+ return NOTHING;
+ }
+ }
+ }
+
+
+ /**
+ * Simple interface that hold a correct <code>writeReplace</code> signature that can be seen by an
+ * <code>ObjectOutputStream</code>.
+ *
+ * It will be applied before the creation of the mock when the mock setting says it should serializable.
+ *
+ * @see #enableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings)
+ */
+ public interface AcrossJVMMockitoMockSerializable {
+ public Object writeReplace() throws java.io.ObjectStreamException;
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java
new file mode 100644
index 0000000..a39e1cf
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.MethodProxy;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+
+class CGLIBHacker {
+
+ public void setMockitoNamingPolicy(MethodProxy methodProxy) {
+ try {
+ Field createInfoField = reflectOnCreateInfo(methodProxy);
+ createInfoField.setAccessible(true);
+ Object createInfo = createInfoField.get(methodProxy);
+ Field namingPolicyField = createInfo.getClass().getDeclaredField("namingPolicy");
+ namingPolicyField.setAccessible(true);
+ if (namingPolicyField.get(createInfo) == null) {
+ namingPolicyField.set(createInfo, MockitoNamingPolicy.INSTANCE);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Unable to set MockitoNamingPolicy on cglib generator which creates FastClasses", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Field reflectOnCreateInfo(MethodProxy methodProxy) throws SecurityException, NoSuchFieldException {
+
+ Class cglibMethodProxyClass = methodProxy.getClass();
+ // in case methodProxy was extended by user, let's traverse the object
+ // graph to find the cglib methodProxy
+ // with all the fields we would like to change
+ while (cglibMethodProxyClass != MethodProxy.class) {
+ cglibMethodProxyClass = methodProxy.getClass().getSuperclass();
+ }
+ return cglibMethodProxyClass.getDeclaredField("createInfo");
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java
new file mode 100644
index 0000000..998ec7e
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.Callback;
+import org.mockito.cglib.proxy.Factory;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.instance.InstantiatorProvider;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+
+/**
+ * A MockMaker that uses cglib to generate mocks on a JVM.
+ */
+public class CglibMockMaker implements MockMaker {
+
+ @Override
+ public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+ InternalMockHandler mockitoHandler = cast(handler);
+ new AcrossJVMSerializationFeature().enableSerializationAcrossJVM(settings);
+ return new ClassImposterizer(new InstantiatorProvider().getInstantiator(settings)).imposterise(
+ new MethodInterceptorFilter(mockitoHandler, settings), settings.getTypeToMock(), settings.getExtraInterfaces());
+ }
+
+ private InternalMockHandler cast(MockHandler handler) {
+ if (!(handler instanceof InternalMockHandler)) {
+ throw new MockitoException("At the moment you cannot provide own implementations of MockHandler." +
+ "\nPlease see the javadocs for the MockMaker interface.");
+ }
+ return (InternalMockHandler) handler;
+ }
+
+ @Override
+ public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+ ((Factory) mock).setCallback(0, new MethodInterceptorFilter(cast(newHandler), settings));
+ }
+
+ @Override
+ public MockHandler getHandler(Object mock) {
+ if (!(mock instanceof Factory)) {
+ return null;
+ }
+ Factory factory = (Factory) mock;
+ Callback callback = factory.getCallback(0);
+ if (!(callback instanceof MethodInterceptorFilter)) {
+ return null;
+ }
+ return ((MethodInterceptorFilter) callback).getHandler();
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java
new file mode 100644
index 0000000..73b191a
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.core.CodeGenerationException;
+import org.mockito.cglib.core.NamingPolicy;
+import org.mockito.cglib.core.Predicate;
+import org.mockito.cglib.proxy.*;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.instance.InstantationException;
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.internal.creation.util.SearchingClassLoader;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.List;
+
+import static org.mockito.internal.util.StringJoiner.join;
+
+/**
+ * Inspired on jMock (thanks jMock guys!!!)
+ */
+public class ClassImposterizer {
+
+ private final Instantiator instantiator;
+
+ public ClassImposterizer(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ private static final NamingPolicy NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES = new MockitoNamingPolicy() {
+ @Override
+ public String getClassName(String prefix, String source, Object key, Predicate names) {
+ return "codegen." + super.getClassName(prefix, source, key, names);
+ }
+ };
+
+ private static final CallbackFilter IGNORE_BRIDGE_METHODS = new CallbackFilter() {
+ @Override
+ public int accept(Method method) {
+ return method.isBridge() ? 1 : 0;
+ }
+ };
+
+ public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Collection<Class> ancillaryTypes) {
+ return (T) imposterise(interceptor, mockedType, ancillaryTypes.toArray(new Class[ancillaryTypes.size()]));
+ }
+
+ public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Class<?>... ancillaryTypes) {
+ Class<Factory> proxyClass = null;
+ Object proxyInstance = null;
+ try {
+ setConstructorsAccessible(mockedType, true);
+ proxyClass = createProxyClass(mockedType, ancillaryTypes);
+ proxyInstance = createProxy(proxyClass, interceptor);
+ return mockedType.cast(proxyInstance);
+ } catch (ClassCastException cce) {
+ throw new MockitoException(join(
+ "ClassCastException occurred while creating the mockito proxy :",
+ " class to mock : " + describeClass(mockedType),
+ " created class : " + describeClass(proxyClass),
+ " proxy instance class : " + describeClass(proxyInstance),
+ " instance creation by : " + instantiator.getClass().getSimpleName(),
+ "",
+ "You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)"
+ ), cce);
+ } finally {
+ setConstructorsAccessible(mockedType, false);
+ }
+ }
+
+ private static String describeClass(Class type) {
+ return type == null? "null" : "'" + type.getCanonicalName() + "', loaded by classloader : '" + type.getClassLoader() + "'";
+ }
+
+ private static String describeClass(Object instance) {
+ return instance == null? "null" : describeClass(instance.getClass());
+ }
+
+ //TODO this method does not belong here
+ public void setConstructorsAccessible(Class<?> mockedType, boolean accessible) {
+ for (Constructor<?> constructor : mockedType.getDeclaredConstructors()) {
+ constructor.setAccessible(accessible);
+ }
+ }
+
+ public Class<Factory> createProxyClass(Class<?> mockedType, Class<?>... interfaces) {
+ if (mockedType == Object.class) {
+ mockedType = ClassWithSuperclassToWorkAroundCglibBug.class;
+ }
+
+ Enhancer enhancer = new Enhancer() {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void filterConstructors(Class sc, List constructors) {
+ // Don't filter
+ }
+ };
+ Class<?>[] allMockedTypes = prepend(mockedType, interfaces);
+ enhancer.setClassLoader(SearchingClassLoader.combineLoadersOf(allMockedTypes));
+ enhancer.setUseFactory(true);
+ if (mockedType.isInterface()) {
+ enhancer.setSuperclass(Object.class);
+ enhancer.setInterfaces(allMockedTypes);
+ } else {
+ enhancer.setSuperclass(mockedType);
+ enhancer.setInterfaces(interfaces);
+ }
+ enhancer.setCallbackTypes(new Class[]{MethodInterceptor.class, NoOp.class});
+ enhancer.setCallbackFilter(IGNORE_BRIDGE_METHODS);
+ if (mockedType.getSigners() != null) {
+ enhancer.setNamingPolicy(NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES);
+ } else {
+ enhancer.setNamingPolicy(MockitoNamingPolicy.INSTANCE);
+ }
+
+ enhancer.setSerialVersionUID(42L);
+
+ try {
+ return enhancer.createClass();
+ } catch (CodeGenerationException e) {
+ if (Modifier.isPrivate(mockedType.getModifiers())) {
+ throw new MockitoException("\n"
+ + "Mockito cannot mock this class: " + mockedType
+ + ".\n"
+ + "Most likely it is a private class that is not visible by Mockito");
+ }
+ throw new MockitoException("\n"
+ + "Mockito cannot mock this class: " + mockedType
+ + "\n"
+ + "Mockito can only mock visible & non-final classes."
+ + "\n"
+ + "If you're not sure why you're getting this error, please report to the mailing list.", e);
+ }
+ }
+
+ private Object createProxy(Class<Factory> proxyClass, final MethodInterceptor interceptor) {
+ Factory proxy;
+ try {
+ proxy = instantiator.newInstance(proxyClass);
+ } catch (InstantationException e) {
+ throw new MockitoException("Unable to create mock instance of type '" + proxyClass.getSuperclass().getSimpleName() + "'", e);
+ }
+ proxy.setCallbacks(new Callback[] {interceptor, SerializableNoOp.SERIALIZABLE_INSTANCE });
+ return proxy;
+ }
+
+ private Class<?>[] prepend(Class<?> first, Class<?>... rest) {
+ Class<?>[] all = new Class<?>[rest.length+1];
+ all[0] = first;
+ System.arraycopy(rest, 0, all, 1, rest.length);
+ return all;
+ }
+
+ public static class ClassWithSuperclassToWorkAroundCglibBug {}
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java
new file mode 100644
index 0000000..83617f6
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.MethodProxy;
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+
+class DelegatingMockitoMethodProxy implements MockitoMethodProxy {
+
+ private final MethodProxy methodProxy;
+
+ public DelegatingMockitoMethodProxy(MethodProxy methodProxy) {
+ this.methodProxy = methodProxy;
+ }
+
+ @Override
+ public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
+ return methodProxy.invokeSuper(target, arguments);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java
new file mode 100644
index 0000000..7360c2f
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.MethodInterceptor;
+import org.mockito.cglib.proxy.MethodProxy;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.MockitoMethod;
+import org.mockito.internal.invocation.SerializableMethod;
+import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
+import org.mockito.internal.progress.SequenceNumber;
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * Should be one instance per mock instance, see CglibMockMaker.
+ */
+public class MethodInterceptorFilter implements MethodInterceptor, Serializable {
+
+ private static final long serialVersionUID = 6182795666612683784L;
+ private final InternalMockHandler handler;
+ final ObjectMethodsGuru objectMethodsGuru = new ObjectMethodsGuru();
+ private final MockCreationSettings mockSettings;
+ private final AcrossJVMSerializationFeature acrossJVMSerializationFeature = new AcrossJVMSerializationFeature();
+
+ public MethodInterceptorFilter(InternalMockHandler handler, MockCreationSettings mockSettings) {
+ this.handler = handler;
+ this.mockSettings = mockSettings;
+ }
+
+ @Override
+ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
+ throws Throwable {
+ if (objectMethodsGuru.isEqualsMethod(method)) {
+ return proxy == args[0];
+ } else if (objectMethodsGuru.isHashCodeMethod(method)) {
+ return hashCodeForMock(proxy);
+ } else if (acrossJVMSerializationFeature.isWriteReplace(method)) {
+ return acrossJVMSerializationFeature.writeReplace(proxy);
+ }
+
+ MockitoMethodProxy mockitoMethodProxy = createMockitoMethodProxy(methodProxy);
+ new CGLIBHacker().setMockitoNamingPolicy(methodProxy);
+
+ MockitoMethod mockitoMethod = createMockitoMethod(method);
+
+ CleanTraceRealMethod realMethod = new CleanTraceRealMethod(mockitoMethodProxy);
+ Invocation invocation = new InvocationImpl(proxy, mockitoMethod, args, SequenceNumber.next(), realMethod);
+ return handler.handle(invocation);
+ }
+
+ public MockHandler getHandler() {
+ return handler;
+ }
+
+ private int hashCodeForMock(Object mock) {
+ return System.identityHashCode(mock);
+ }
+
+ public MockitoMethodProxy createMockitoMethodProxy(MethodProxy methodProxy) {
+ if (mockSettings.isSerializable())
+ return new SerializableMockitoMethodProxy(methodProxy);
+ return new DelegatingMockitoMethodProxy(methodProxy);
+ }
+
+ public MockitoMethod createMockitoMethod(Method method) {
+ if (mockSettings.isSerializable()) {
+ return new SerializableMethod(method);
+ } else {
+ return new DelegatingMethod(method);
+ }
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt
new file mode 100644
index 0000000..5a311f7
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java
new file mode 100644
index 0000000..4b9152f
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.core.DefaultNamingPolicy;
+
+class MockitoNamingPolicy extends DefaultNamingPolicy {
+
+ public static final MockitoNamingPolicy INSTANCE = new MockitoNamingPolicy();
+
+ @Override
+ protected String getTag() {
+ return "ByMockitoWithCGLIB";
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java
new file mode 100644
index 0000000..cd7419d
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.MethodProxy;
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+import org.mockito.internal.util.reflection.Whitebox;
+
+import java.io.Serializable;
+
+class SerializableMockitoMethodProxy implements MockitoMethodProxy, Serializable {
+
+ private static final long serialVersionUID = -5337859962876770632L;
+ private final Class<?> c1;
+ private final Class<?> c2;
+ private final String desc;
+ private final String name;
+ private final String superName;
+ transient MethodProxy methodProxy;
+
+ public SerializableMockitoMethodProxy(MethodProxy methodProxy) {
+ assert methodProxy != null;
+ Object info = Whitebox.getInternalState(methodProxy, "createInfo");
+ c1 = (Class<?>) Whitebox.getInternalState(info, "c1");
+ c2 = (Class<?>) Whitebox.getInternalState(info, "c2");
+ desc = methodProxy.getSignature().getDescriptor();
+ name = methodProxy.getSignature().getName();
+ superName = methodProxy.getSuperName();
+ this.methodProxy = methodProxy;
+ }
+
+ private MethodProxy getMethodProxy() {
+ if (methodProxy == null) {
+ methodProxy = MethodProxy.create(c1, c2, desc, name, superName);
+ }
+ return methodProxy;
+ }
+
+ @Override
+ public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
+ return getMethodProxy().invokeSuper(target, arguments);
+ }
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java
new file mode 100644
index 0000000..1bc21e7
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.cglib.proxy.Callback;
+import org.mockito.cglib.proxy.NoOp;
+
+import java.io.Serializable;
+
+/**
+ * Offer a Serializable implementation of the NoOp CGLIB callback.
+ */
+class SerializableNoOp implements NoOp, Serializable {
+
+ private static final long serialVersionUID = 7434976328690189159L;
+ public static final Callback SERIALIZABLE_INSTANCE = new SerializableNoOp();
+
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/package-info.java b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/package-info.java
new file mode 100644
index 0000000..e63e190
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/repackaged/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Mockito related CGLIB stuff. Repackaged from Mockito 1.10.19 with public visibility.
+ */
+package org.powermock.api.mockito.repackaged;
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java b/api/mockito/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java
new file mode 100644
index 0000000..5e0a2a1
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.verification;
+
+public interface ConstructorArgumentsVerification {
+
+ void withArguments(Object argument, Object... additionalArguments) throws Exception;
+
+ void withNoArguments() throws Exception;
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java b/api/mockito/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java
new file mode 100644
index 0000000..66589a0
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.verification;
+
+import java.lang.reflect.Method;
+
+public interface PrivateMethodVerification {
+
+ /**
+ * Verify calls to private methods without having to specify the method
+ * name. The method will be looked up using the parameter types (if
+ * possible).
+ *
+ * @throws Exception If something unexpected goes wrong.
+ */
+ public void invoke(Object... arguments) throws Exception;
+
+ /**
+ * Verify calls to the specific method.
+ *
+ * @throws Exception If something unexpected goes wrong.
+ */
+ public WithOrWithoutVerifiedArguments invoke(Method method) throws Exception;
+
+ /**
+ * Verify a private method call by specifying the method name of the method
+ * to verify.
+ *
+ * @throws Exception If something unexpected goes wrong.
+ * @see {@link #invoke(Object...)}
+ */
+ public void invoke(String methodToVerify, Object... arguments) throws Exception;
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java
new file mode 100644
index 0000000..711e387
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.verification;
+
+public interface WithOrWithoutVerifiedArguments extends WithVerifiedArguments, WithoutVerifiedArguments {
+}
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java
new file mode 100644
index 0000000..88ec342
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.verification;
+
+
+public interface WithVerifiedArguments {
+
+ public abstract void withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java
new file mode 100644
index 0000000..3c374f5
--- /dev/null
+++ b/api/mockito/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.verification;
+
+public interface WithoutVerifiedArguments {
+
+ public void withNoArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker b/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..0388d5c
--- /dev/null
+++ b/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+org.powermock.api.mockito.internal.mockmaker.PowerMockMaker
\ No newline at end of file
diff --git a/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider b/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider
new file mode 100644
index 0000000..7f689ce
--- /dev/null
+++ b/api/mockito/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider
@@ -0,0 +1 @@
+org.powermock.api.mockito.internal.exceptions.StackTraceCleanerProvider
\ No newline at end of file
diff --git a/api/mockito/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java b/api/mockito/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java
new file mode 100644
index 0000000..053831e
--- /dev/null
+++ b/api/mockito/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.powermock.reflect.Whitebox;
+
+/**
+ * @author Stanislav Chizhov
+ */
+public class DefaultMethodExpectationSetupTest {
+
+ private final CUT object = new CUT();
+
+ @Test(expected = MissingMethodInvocationException.class)
+ public void testWithArguments_Multiple() throws Exception {
+ DefaultMethodExpectationSetup s = new DefaultMethodExpectationSetup(object, object.getClass().getMethod("multiple", Object.class, Object.class, Object.class));
+ Object a1 = new Object();
+ Object a2 = new Object();
+ Object a3 = new Object();
+ s.withArguments(a1, a2, a3);
+ }
+
+ @Test(expected = MissingMethodInvocationException.class)
+ public void testWithArguments_Single() throws Exception {
+ DefaultMethodExpectationSetup s = new DefaultMethodExpectationSetup(object, object.getClass().getMethod("single", Object.class));
+ Object a1 = new Object();
+ s.withArguments(a1);
+ }
+
+ @Test
+ public void testJoin() throws Exception {
+ Object a1 = new Object();
+ Object a2 = new Object();
+ Object a3 = new Object();
+ Object[] res = Whitebox.invokeMethod(DefaultMethodExpectationSetup.class, "join", a1, new Object[]{a2, a3});
+
+ Assert.assertArrayEquals(new Object[]{a1, a2, a3}, res);
+ }
+
+ public static class CUT {
+
+ public void multiple(Object a1, Object a2, Object a3) {
+ //Nada
+ }
+
+ public void single(Object a1) {
+ //Nada
+ }
+ }
+}
diff --git a/api/mockito/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java b/api/mockito/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java
new file mode 100644
index 0000000..8f93488
--- /dev/null
+++ b/api/mockito/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java
@@ -0,0 +1,43 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.mock.MockName;
+
+public class MockCreatorTest {
+
+ private final MockUtil util = new MockUtil();
+
+ @Test
+ public void testMock_shouldReturnMockNameWhenSettingsHaveName()
+ throws NoSuchMethodException, SecurityException {
+ final MockSettingsImpl<List<?>> settings = new MockSettingsImpl<List<?>>();
+ settings.name("mylist");
+
+ final List<?> result = MockCreator.mock(List.class, false, false, null,
+ settings, List.class.getMethod("add", Object.class));
+
+ final MockName mockName = util.getMockName(result);
+ assertNotNull(mockName);
+ assertEquals("mylist", mockName.toString());
+ }
+
+ @Test
+ public void testMock_shouldReturnClassNameWhenSettingsHaveNoName()
+ throws NoSuchMethodException, SecurityException {
+ final MockSettingsImpl<List<?>> settings = new MockSettingsImpl<List<?>>();
+
+ final List<?> result = MockCreator.mock(List.class, false, false, null,
+ settings, List.class.getMethod("add", Object.class));
+
+ final MockName mockName = util.getMockName(result);
+ assertNotNull(mockName);
+ assertEquals("list", mockName.toString());
+ }
+}
diff --git a/api/mockito/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java b/api/mockito/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java
new file mode 100644
index 0000000..feba476
--- /dev/null
+++ b/api/mockito/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java
@@ -0,0 +1,54 @@
+package org.powermock.api.mockito.internal.stubbing.answers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+/**
+ * Created by gauee on 12/11/15.
+ */
+public class ChainReturnsTest {
+
+ public static final String ANSWER_FIRST = "answerFirst";
+ public static final String ANSWER_SECOND = "answerSecond";
+ private InvocationOnMock invocationOnMock;
+
+ @Before
+ public void init() {
+ this.invocationOnMock = mock(InvocationOnMock.class);
+ }
+
+
+ @Test
+ public void returnsTwoDifferentAnswers() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, ANSWER_SECOND);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_FIRST)));
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_SECOND)));
+ }
+
+ @Test
+ public void returnsFirstAnswerAndNullValue() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, null);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_FIRST)));
+ assertThat(chainReturns.answer(invocationOnMock), is(nullValue()));
+ }
+
+ @Test
+ public void returnsAlwaysLastDeclaredAnswer() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, ANSWER_SECOND);
+
+ chainReturns.answer(invocationOnMock);
+ chainReturns.answer(invocationOnMock);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_SECOND)));
+ }
+
+}
\ No newline at end of file
diff --git a/api/mockito2/pom.xml b/api/mockito2/pom.xml
new file mode 100644
index 0000000..686d87a
--- /dev/null
+++ b/api/mockito2/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-api-mockito2</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock API for Mockito 2.+.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito2.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/api/mockito2/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java b/api/mockito2/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
new file mode 100644
index 0000000..14a6b58
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/extension/listener/AnnotationEnabler.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.extension.listener;
+
+import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.MockSettings;
+import org.mockito.MockitoAnnotations.Mock;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+import org.mockito.internal.util.reflection.GenericMaster;
+import org.powermock.api.mockito.internal.configuration.PowerMockitoInjectingAnnotationEngine;
+import org.powermock.core.spi.listener.AnnotationEnablerListener;
+import org.powermock.core.spi.support.AbstractPowerMockTestListenerBase;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+import static org.mockito.Mockito.withSettings;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+/**
+ * Before each test method all fields annotated with {@link Mock},
+ * {@link org.mockito.Mock} or {@link Mock} have mock objects created for them
+ * and injected to the fields. It will also delegate to a special implementation
+ * of the {@link InjectingAnnotationEngine} in Mockito which inject's spies,
+ * captors etc.
+ * <p/>
+ * It will only inject to fields that haven't been set before (i.e that are
+ * <code>null</code>).
+ */
+ at SuppressWarnings("deprecation")
+public class AnnotationEnabler extends AbstractPowerMockTestListenerBase implements AnnotationEnablerListener {
+
+ @Override
+ public void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception {
+ standardInject(testInstance);
+ injectSpiesAndInjectToSetters(testInstance);
+ injectCaptor(testInstance);
+ }
+
+ private void injectSpiesAndInjectToSetters(Object testInstance) {
+ new PowerMockitoInjectingAnnotationEngine().process(testInstance.getClass(), testInstance);
+ }
+
+ private void injectCaptor(Object testInstance) throws Exception {
+ Set<Field> fieldsAnnotatedWithCaptor = Whitebox.getFieldsAnnotatedWith(testInstance, Captor.class);
+ for (Field field : fieldsAnnotatedWithCaptor) {
+ final Object captor = processAnnotationOn(field.getAnnotation(Captor.class), field);
+ field.set(testInstance, captor);
+ }
+ }
+
+ private void standardInject(Object testInstance) throws IllegalAccessException {
+ Set<Field> fields = Whitebox.getFieldsAnnotatedWith(testInstance, getMockAnnotations());
+ for (Field field : fields) {
+ if (field.get(testInstance) != null) {
+ continue;
+ }
+ final Class<?> type = field.getType();
+ if (field.isAnnotationPresent(org.powermock.core.classloader.annotations.Mock.class)) {
+ org.powermock.core.classloader.annotations.Mock annotation = field
+ .getAnnotation(org.powermock.core.classloader.annotations.Mock.class);
+ final String[] value = annotation.value();
+ if (value.length != 1 || !"".equals(value[0])) {
+ System.err
+ .println("PowerMockito deprecation: Use PowerMockito.spy(..) for partial mocking instead. A standard mock will be created instead.");
+ }
+ }
+
+ if (field.isAnnotationPresent(org.mockito.Mock.class)) {
+ org.mockito.Mock mockAnnotation = field.getAnnotation(org.mockito.Mock.class);
+ MockSettings mockSettings = withSettings();
+ Answers answers = mockAnnotation.answer();
+ if (answers != null) {
+ mockSettings.defaultAnswer(answers.get());
+ }
+
+ Class<?>[] extraInterfaces = mockAnnotation.extraInterfaces();
+ if (extraInterfaces != null && extraInterfaces.length > 0) {
+ mockSettings.extraInterfaces(extraInterfaces);
+ }
+
+ String name = mockAnnotation.name();
+ if (name != null && name.length() > 0) {
+ mockSettings.name(name);
+ }
+
+ field.set(testInstance, mock(type, mockSettings));
+ } else {
+ field.set(testInstance, mock(type));
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Class<? extends Annotation>[] getMockAnnotations() {
+ return new Class[]{org.mockito.Mock.class, Mock.class, org.powermock.core.classloader.annotations.Mock.class};
+ }
+
+ private Object processAnnotationOn(Captor annotation, Field field) {
+ Class<?> type = field.getType();
+ if (!ArgumentCaptor.class.isAssignableFrom(type)) {
+ throw new MockitoException("@Captor field must be of the type ArgumentCaptor.\n" + "Field: '"
+ + field.getName() + "' has wrong type\n"
+ + "For info how to use @Captor annotations see examples in javadoc for MockitoAnnotations class.");
+ }
+ Class cls = new GenericMaster().getGenericType(field);
+ return ArgumentCaptor.forClass(cls);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java b/api/mockito2/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
new file mode 100644
index 0000000..a02ebe7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.extension.proxyframework;
+
+import org.powermock.api.mockito.repackaged.cglib.proxy.Enhancer;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Factory;
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ * CGLib proxy framework setup.
+ */
+public class ProxyFrameworkImpl implements ProxyFramework {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Class<?> getUnproxiedType(Class<?> type) {
+ Class<?> currentType = type;
+ while (isProxy(currentType)) {
+ for (Class<?> i : currentType.getInterfaces()) {
+ if (!i.getName().equals(Factory.class.getName())) {
+ return i;
+ }
+ }
+ currentType = currentType.getSuperclass();
+ }
+ return currentType;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isProxy(Class<?> type) {
+ if (type == null) {
+ return false;
+ }
+ return type.getName().contains("$$EnhancerByMockitoWithCGLIB$$") || Enhancer.isEnhanced(type);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/PowerMockito.java b/api/mockito2/src/main/java/org/powermock/api/mockito/PowerMockito.java
new file mode 100644
index 0000000..b161636
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/PowerMockito.java
@@ -0,0 +1,800 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.stubbing.answers.CallsRealMethods;
+import org.mockito.internal.stubbing.answers.DoesNothing;
+import org.mockito.internal.stubbing.answers.Returns;
+import org.mockito.internal.stubbing.answers.ThrowsException;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.expectation.ConstructorExpectationSetup;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+import org.powermock.api.mockito.internal.PowerMockitoCore;
+import org.powermock.api.mockito.internal.expectation.ConstructorAwareExpectationSetup;
+import org.powermock.api.mockito.internal.expectation.DefaultConstructorExpectationSetup;
+import org.powermock.api.mockito.internal.expectation.DefaultMethodExpectationSetup;
+import org.powermock.api.mockito.internal.mockcreation.MockCreator;
+import org.powermock.api.mockito.internal.stubbing.answers.ChainReturns;
+import org.powermock.api.mockito.internal.verification.DefaultConstructorArgumentsVerfication;
+import org.powermock.api.mockito.internal.verification.DefaultPrivateMethodVerification;
+import org.powermock.api.mockito.internal.verification.VerifyNoMoreInteractions;
+import org.powermock.api.mockito.verification.ConstructorArgumentsVerification;
+import org.powermock.api.mockito.verification.PrivateMethodVerification;
+import org.powermock.api.support.membermodification.MemberModifier;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.withSettings;
+
+/**
+ * PowerMockito extends Mockito functionality with several new features such as
+ * mocking static and private methods and more. Use PowerMock instead of Mockito
+ * where applicable.
+ *
+ * @see Mockito
+ */
+public class PowerMockito extends MemberModifier {
+ private static final String NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE = "No instantiation of class %s was recorded during the test. Note that only expected object creations (e.g. those using whenNew(..)) can be verified.";
+ private static final PowerMockitoCore POWERMOCKITO_CORE = new PowerMockitoCore();
+
+ /**
+ * Enable static mocking for all methods of a class.
+ *
+ * @param type
+ * the class to enable static mocking
+ */
+ public static synchronized void mockStatic(Class<?> type, Class<?>... types) {
+ MockCreator.mock(type, true, false, null, null, (Method[]) null);
+ if(types != null && types.length > 0) {
+ for (Class<?> aClass : types) {
+ MockCreator.mock(aClass, true, false, null, null, (Method[]) null);
+ }
+ }
+ }
+
+ /**
+ * Creates class mock with a specified strategy for its answers to
+ * interactions. It's quite advanced feature and typically you don't need it
+ * to write decent tests. However it can be helpful when working with legacy
+ * systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b>
+ * stub the method call.
+ *
+ * <pre>
+ * mockStatic(Foo.class, RETURNS_SMART_NULLS);
+ * mockStatic(Foo.class, new YourOwnAnswer());
+ * </pre>
+ *
+ * @param classMock
+ * class to mock
+ * @param defaultAnswer
+ * default answer for unstubbed methods
+ *
+ * @return mock object
+ */
+ public static void mockStatic(Class<?> classMock, @SuppressWarnings("rawtypes") Answer defaultAnswer) {
+ mockStatic(classMock, withSettings().defaultAnswer(defaultAnswer));
+ }
+
+ /**
+ * Creates a class mock with some non-standard settings.
+ * <p>
+ * The number of configuration points for a mock grows so we need a fluent
+ * way to introduce new configuration without adding more and more
+ * overloaded PowerMockito.mockStatic() methods. Hence {@link MockSettings}.
+ *
+ * <pre>
+ * mockStatic(Listener.class, withSettings()
+ * .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+ * );
+ * </pre>
+ *
+ * <b>Use it carefully and occasionally</b>. What might be reason your test
+ * needs non-standard mocks? Is the code under test so complicated that it
+ * requires non-standard mocks? Wouldn't you prefer to refactor the code
+ * under test so it is testable in a simple way?
+ * <p>
+ * See also {@link Mockito#withSettings()}
+ *
+ * @param classToMock
+ * class to mock
+ * @param mockSettings
+ * additional mock settings
+ * @return mock object
+ */
+ public static void mockStatic(Class<?> classToMock, MockSettings mockSettings) {
+ MockCreator.mock(classToMock, true, false, null, mockSettings, (Method[]) null);
+ }
+
+ /**
+ * Creates a mock object that supports mocking of final and native methods.
+ *
+ * @param <T>
+ * the type of the mock object
+ * @param type
+ * the type of the mock object
+ * @return the mock object.
+ */
+ public static synchronized <T> T mock(Class<T> type) {
+ return MockCreator.mock(type, false, false, null, null, (Method[]) null);
+ }
+
+ /**
+ * Creates mock with a specified strategy for its answers to interactions.
+ * It's quite advanced feature and typically you don't need it to write
+ * decent tests. However it can be helpful when working with legacy systems.
+ * <p>
+ * It is the default answer so it will be used <b>only when you don't</b>
+ * stub the method call.
+ *
+ * <pre>
+ * Foo mock = mock(Foo.class, RETURNS_SMART_NULLS);
+ * Foo mockTwo = mock(Foo.class, new YourOwnAnswer());
+ * </pre>
+ *
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ * </p>
+ *
+ * @param classToMock
+ * class or interface to mock
+ * @param defaultAnswer
+ * default answer for unstubbed methods
+ *
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, @SuppressWarnings("rawtypes") Answer defaultAnswer) {
+ return mock(classToMock, withSettings().defaultAnswer(defaultAnswer));
+ }
+
+ /**
+ * Creates a mock with some non-standard settings.
+ * <p>
+ * The number of configuration points for a mock grows so we need a fluent
+ * way to introduce new configuration without adding more and more
+ * overloaded Mockito.mock() methods. Hence {@link MockSettings}.
+ *
+ * <pre>
+ * Listener mock = mock(Listener.class, withSettings()
+ * .name("firstListner").defaultBehavior(RETURNS_SMART_NULLS));
+ * );
+ * </pre>
+ *
+ * <b>Use it carefully and occasionally</b>. What might be reason your test
+ * needs non-standard mocks? Is the code under test so complicated that it
+ * requires non-standard mocks? Wouldn't you prefer to refactor the code
+ * under test so it is testable in a simple way?
+ * <p>
+ * See also {@link Mockito#withSettings()}
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param classToMock
+ * class or interface to mock
+ * @param mockSettings
+ * additional mock settings
+ * @return mock object
+ */
+ public static <T> T mock(Class<T> classToMock, MockSettings mockSettings) {
+ return MockCreator.mock(classToMock, false, false, null, mockSettings, (Method[]) null);
+ }
+
+ /**
+ * Spy on objects that are final or otherwise not "spyable" from
+ * normal Mockito.
+ *
+ * @see Mockito#spy(Object)
+ *
+ * @param <T>
+ * the type of the mock object
+ * @param object
+ * the object to spy on
+ * @return the spy object.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T spy(T object) {
+ return MockCreator.mock((Class<T>) Whitebox.getType(object), false, true, object, null, (Method[]) null);
+ }
+
+ /**
+ * Spy on classes (not "spyable" from normal Mockito).
+ *
+ * @see Mockito#spy(Object)
+ *
+ * @param <T>
+ * the type of the class mock
+ * @param type
+ * the type of the class mock
+ */
+ public static synchronized <T> void spy(Class<T> type) {
+ MockCreator.mock(type, true, true, type, null, (Method[]) null);
+ }
+
+ /**
+ * Verifies certain behavior <b>happened once</b>
+ * <p>
+ * Alias to <code>verifyStatic(times(1))</code> E.g:
+ *
+ * <pre>
+ * verifyStatic();
+ * ClassWithStaticMethod.someStaticMethod("some arg");
+ * </pre>
+ *
+ * Above is equivalent to:
+ *
+ * <pre>
+ * verifyStatic(times(1));
+ * ClassWithStaticMethod.someStaticMethod("some arg");
+ * </pre>
+ *
+ * <p>
+ * Although it is possible to verify a stubbed invocation, usually <b>it's
+ * just redundant</b>. Let's say you've stubbed foo.bar(). If your code
+ * cares what foo.bar() returns then something else breaks(often before even
+ * verify() gets executed). If your code doesn't care what get(0) returns
+ * then it should not be stubbed.
+ */
+ public static synchronized void verifyStatic() {
+ verifyStatic(times(1));
+ }
+
+ /**
+ * Verifies certain behavior happened at least once / exact number of times
+ * / never. E.g:
+ *
+ * <pre>
+ * verifyStatic(times(5));
+ * ClassWithStaticMethod.someStaticMethod("was called five times");
+ *
+ * verifyStatic(atLeast(2));
+ * ClassWithStaticMethod.someStaticMethod("was called at least two times");
+ *
+ * //you can use flexible argument matchers, e.g:
+ * verifyStatic(atLeastOnce());
+ * ClassWithStaticMethod.someMethod(<b>anyString()</b>);
+ * </pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ *
+ * @param verificationMode
+ * times(x), atLeastOnce() or never()
+ */
+ public static synchronized void verifyStatic(VerificationMode verificationMode) {
+ Whitebox.getInternalState(Mockito.class, MockingProgress.class).verificationStarted(
+ POWERMOCKITO_CORE.wrapInStaticVerificationMode(verificationMode));
+ }
+
+ /**
+ * Verify a private method invocation for an instance.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Object object) throws Exception {
+ return verifyPrivate(object, times(1));
+ }
+
+ /**
+ * Verify a private method invocation with a given verification mode.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Object object, VerificationMode verificationMode)
+ throws Exception {
+ Whitebox.getInternalState(Mockito.class, MockingProgress.class).verificationStarted(
+ POWERMOCKITO_CORE.wrapInMockitoSpecificVerificationMode(object, verificationMode));
+ return new DefaultPrivateMethodVerification(object);
+ }
+
+ /**
+ * Verify a private method invocation for a class.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Class<?> clazz) throws Exception {
+ return verifyPrivate((Object) clazz);
+ }
+
+ /**
+ * Verify a private method invocation for a class with a given verification
+ * mode.
+ *
+ * @see {@link Mockito#verify(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static PrivateMethodVerification verifyPrivate(Class<?> clazz, VerificationMode verificationMode)
+ throws Exception {
+ return verifyPrivate((Object) clazz, verificationMode);
+ }
+
+ /**
+ * Verifies certain behavior <b>happened once</b>
+ * <p>
+ * Alias to <code>verifyNew(mockClass, times(1))</code> E.g:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class);
+ * </pre>
+ *
+ * Above is equivalent to:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class, times(1));
+ * </pre>
+ *
+ * <p>
+ *
+ * @param mock
+ * Class mocked by PowerMock.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> ConstructorArgumentsVerification verifyNew(Class<T> mock) {
+ if (mock == null) {
+ throw new IllegalArgumentException("Class to verify cannot be null");
+ }
+ NewInvocationControl<?> invocationControl = MockRepository.getNewInstanceControl(mock);
+ if (invocationControl == null) {
+ throw new IllegalStateException(String.format(NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE, Whitebox.getType(
+ mock).getName()));
+ }
+ invocationControl.verify();
+ return new DefaultConstructorArgumentsVerfication<T>((NewInvocationControl<T>) invocationControl, mock);
+ }
+
+ /**
+ * Verifies certain behavior happened at least once / exact number of times
+ * / never. E.g:
+ *
+ * <pre>
+ * verifyNew(ClassWithStaticMethod.class, times(5));
+ *
+ * verifyNew(ClassWithStaticMethod.class, atLeast(2));
+ *
+ * //you can use flexible argument matchers, e.g:
+ * verifyNew(ClassWithStaticMethod.class, atLeastOnce());
+ * </pre>
+ *
+ * <b>times(1) is the default</b> and can be omitted
+ * <p>
+ *
+ * @param mock
+ * to be verified
+ * @param mode
+ * times(x), atLeastOnce() or never()
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> ConstructorArgumentsVerification verifyNew(Class<?> mock, VerificationMode mode) {
+ if (mock == null) {
+ throw new IllegalArgumentException("Class to verify cannot be null");
+ } else if (mode == null) {
+ throw new IllegalArgumentException("Verify mode cannot be null");
+ }
+ NewInvocationControl<?> invocationControl = MockRepository.getNewInstanceControl(mock);
+ MockRepository.putAdditionalState("VerificationMode", POWERMOCKITO_CORE.wrapInMockitoSpecificVerificationMode(
+ mock, mode));
+ if (invocationControl == null) {
+ throw new IllegalStateException(String.format(NO_OBJECT_CREATION_ERROR_MESSAGE_TEMPLATE, Whitebox.getType(
+ mock).getName()));
+ }
+ try {
+ invocationControl.verify();
+ } finally {
+ MockRepository.removeAdditionalState("VerificationMode");
+ }
+ return new DefaultConstructorArgumentsVerfication<T>((NewInvocationControl<T>) invocationControl, mock);
+ }
+
+ /**
+ * Expect calls to private methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Object instance, String methodName, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(instance, methodName, arguments));
+ }
+
+ /**
+ * Expect calls to private methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> WithOrWithoutExpectedArguments<T> when(Object instance, Method method) throws Exception {
+ return new DefaultMethodExpectationSetup<T>(instance, method);
+ }
+
+ /**
+ * Expect calls to private static methods.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> WithOrWithoutExpectedArguments<T> when(Class<?> cls, Method method) throws Exception {
+ return new DefaultMethodExpectationSetup<T>(cls, method);
+ }
+
+ /**
+ * Expect calls to private methods without having to specify the method
+ * name. The method will be looked up using the parameter types (if
+ * possible).
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Object instance, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(instance, arguments));
+ }
+
+ /**
+ * Expect a static private or inner class method call.
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Class<?> clazz, String methodToExpect, Object... arguments)
+ throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(clazz, methodToExpect, arguments));
+ }
+
+ /**
+ * Expect calls to private static methods without having to specify the
+ * method name. The method will be looked up using the parameter types if
+ * possible
+ *
+ * @see {@link Mockito#when(Object)}
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ public static <T> OngoingStubbing<T> when(Class<?> klass, Object... arguments) throws Exception {
+ return Mockito.when(Whitebox.<T> invokeMethod(klass, arguments));
+ }
+
+ /**
+ * Just delegates to the original {@link Mockito#when(Object)} method.
+ *
+ * @see {@link Mockito#when(Object)}
+ */
+ public static <T> OngoingStubbing<T> when(T methodCall) {
+ return Mockito.when(methodCall);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ */
+ public static synchronized <T> WithOrWithoutExpectedArguments<T> whenNew(Constructor<T> ctor) {
+ return new ConstructorAwareExpectationSetup<T>(ctor);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations. For example you might
+ * want to throw an exception or return a mock.
+ */
+ public static synchronized <T> ConstructorExpectationSetup<T> whenNew(Class<T> type) {
+ return new DefaultConstructorExpectationSetup<T>(type);
+ }
+
+ /**
+ * Allows specifying expectations on new invocations for private member
+ * (inner) classes, local or anonymous classes. For example you might want
+ * to throw an exception or return a mock.
+ *
+ * @param fullyQualifiedName
+ * The fully-qualified name of the inner/local/anonymous type to
+ * expect.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> ConstructorExpectationSetup<T> whenNew(String fullyQualifiedName) throws Exception {
+ final Class<T> forName = (Class<T>) Class.forName(fullyQualifiedName);
+ return new DefaultConstructorExpectationSetup<T>(forName);
+ }
+
+ /**
+ * Checks if any of given mocks (can be both instance and class mocks) has
+ * any unverified interaction. Delegates to the orignal
+ * {@link Mockito#verifyNoMoreInteractions(Object...)} if the mock is not a
+ * PowerMockito mock.
+ * <p>
+ * You can use this method after you verified your mocks - to make sure that
+ * nothing else was invoked on your mocks.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates
+ * the intent well.
+ * <p>
+ * Stubbed invocations (if called) are also treated as interactions.
+ * <p>
+ * A word of <b>warning</b>: Some users who did a lot of classic,
+ * expect-run-verify mocking tend to use verifyNoMoreInteractions() very
+ * often, even in every test method. verifyNoMoreInteractions() is not
+ * recommended to use in every test method. verifyNoMoreInteractions() is a
+ * handy assertion from the interaction testing toolkit. Use it only when
+ * it's relevant. Abusing it leads to overspecified, less maintainable
+ * tests. You can find further reading <a href=
+ * "http://monkeyisland.pl/2008/07/12/should-i-worry-about-the-unexpected/"
+ * >here</a>.
+ * <p>
+ * This method will also detect unverified invocations that occurred before
+ * the test method, for example: in setUp(), @Before method or in
+ * constructor. Consider writing nice code that makes interactions only in
+ * test methods.
+ *
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * //interactions
+ * mock.doSomething();
+ * mock.doSomethingUnexpected();
+ *
+ * //verification
+ * verify(mock).doSomething();
+ *
+ * //following will fail because 'doSomethingUnexpected()' is unexpected
+ * verifyNoMoreInteractions(mock);
+ *
+ * </pre>
+ *
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks
+ * to be verified
+ */
+ public static void verifyNoMoreInteractions(Object... mocks) {
+ VerifyNoMoreInteractions.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * Verifies that no interactions happened on given mocks (can be both
+ * instance and class mocks). Delegates to the orignal
+ * {@link Mockito#verifyNoMoreInteractions(Object...)} if the mock is not a
+ * PowerMockito mock.
+ *
+ * <pre>
+ * verifyZeroInteractions(mockOne, mockTwo);
+ * </pre>
+ *
+ * This method will also detect invocations that occurred before the test
+ * method, for example: in setUp(), @Before method or in constructor.
+ * Consider writing nice code that makes interactions only in test methods.
+ * <p>
+ * See also {@link Mockito#never()} - it is more explicit and communicates
+ * the intent well.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param mocks
+ * to be verified
+ */
+ public static void verifyZeroInteractions(Object... mocks) {
+ VerifyNoMoreInteractions.verifyNoMoreInteractions(mocks);
+ }
+
+ /**
+ * Use doAnswer() when you want to stub a void method with generic
+ * {@link Answer}.
+ * <p>
+ * Stubbing voids requires different approach from
+ * {@link Mockito#when(Object)} because the compiler does not like void
+ * methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doAnswer(new Answer() {
+ * public Object answer(InvocationOnMock invocation) {
+ * Object[] args = invocation.getArguments();
+ * Mock mock = invocation.getMock();
+ * return null;
+ * }
+ * }).when(mock).someMethod();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param answer
+ * to answer when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doAnswer(Answer<?> answer) {
+ return POWERMOCKITO_CORE.doAnswer(answer);
+ }
+
+ /**
+ * Use doThrow() when you want to stub the void method with an exception.
+ * <p>
+ * Stubbing voids requires different approach from
+ * {@link Mockito#when(Object)} because the compiler does not like void
+ * methods inside brackets...
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(mock).someVoidMethod();
+ * </pre>
+ *
+ * @param toBeThrown
+ * to be thrown when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doThrow(Throwable toBeThrown) {
+ return POWERMOCKITO_CORE.doAnswer(new ThrowsException(toBeThrown));
+ }
+
+ /**
+ * Use doCallRealMethod() when you want to call the real implementation of a
+ * method.
+ * <p>
+ * As usual you are going to read <b>the partial mock warning</b>: Object
+ * oriented programming is more less tackling complexity by dividing the
+ * complexity into separate, specific, SRPy objects. How does partial mock
+ * fit into this paradigm? Well, it just doesn't... Partial mock usually
+ * means that the complexity has been moved to a different method on the
+ * same object. In most cases, this is not the way you want to design your
+ * application.
+ * <p>
+ * However, there are rare cases when partial mocks come handy: dealing with
+ * code you cannot change easily (3rd party interfaces, interim refactoring
+ * of legacy code etc.) However, I wouldn't use partial mocks for new,
+ * test-driven & well-designed code.
+ * <p>
+ * See also javadoc {@link Mockito#spy(Object)} to find out more about
+ * partial mocks. <b>Mockito.spy() is a recommended way of creating partial
+ * mocks.</b> The reason is it guarantees real methods are called against
+ * correctly constructed object because you're responsible for constructing
+ * the object passed to spy() method.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * Foo mock = mock(Foo.class);
+ * doCallRealMethod().when(mock).someVoidMethod();
+ *
+ * // this will call the real implementation of Foo.someVoidMethod()
+ * mock.someVoidMethod();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doCallRealMethod() {
+ return POWERMOCKITO_CORE.doAnswer(new CallsRealMethods());
+ }
+
+ /**
+ * Use doNothing() for setting void methods to do nothing. <b>Beware that
+ * void methods on mocks do nothing by default!</b> However, there are rare
+ * situations when doNothing() comes handy:
+ * <p>
+ * 1. Stubbing consecutive calls on a void method:
+ *
+ * <pre>
+ * doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();
+ *
+ * //does nothing the first time:
+ * mock.someVoidMethod();
+ *
+ * //throws RuntimeException the next time:
+ * mock.someVoidMethod();
+ * </pre>
+ *
+ * 2. When you spy real objects and you want the void method to do nothing:
+ *
+ * <pre>
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //let's make clear() do nothing
+ * doNothing().when(spy).clear();
+ *
+ * spy.add("one");
+ *
+ * //clear() does nothing, so the list still contains "one"
+ * spy.clear();
+ * </pre>
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doNothing() {
+ return POWERMOCKITO_CORE.doAnswer(new DoesNothing());
+ }
+
+ /**
+ * Use doReturn() in those rare occasions when you cannot use
+ * {@link Mockito#when(Object)}.
+ * <p>
+ * <b>Beware that {@link Mockito#when(Object)} is always recommended for
+ * stubbing because it is argument type-safe and more readable</b>
+ * (especially when stubbing consecutive calls).
+ * <p>
+ * Here are those rare occasions when doReturn() comes handy:
+ * <p>
+ *
+ * 1. When spying real objects and calling real methods on a spy brings side
+ * effects
+ *
+ * <pre>
+ * List list = new LinkedList();
+ * List spy = spy(list);
+ *
+ * //Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
+ * when(spy.get(0)).thenReturn("foo");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("foo").when(spy).get(0);
+ * </pre>
+ *
+ * 2. Overriding a previous exception-stubbing:
+ *
+ * <pre>
+ * when(mock.foo()).thenThrow(new RuntimeException());
+ *
+ * //Impossible: the exception-stubbed foo() method is called so RuntimeException is thrown.
+ * when(mock.foo()).thenReturn("bar");
+ *
+ * //You have to use doReturn() for stubbing:
+ * doReturn("bar").when(mock).foo();
+ * </pre>
+ *
+ * Above scenarios shows a tradeoff of Mockito's ellegant syntax. Note that
+ * the scenarios are very rare, though. Spying should be sporadic and
+ * overriding exception-stubbing is very rare.
+ * <p>
+ * See examples in javadoc for {@link Mockito} class
+ *
+ * @param toBeReturned
+ * to be returned when the stubbed method is called
+ * @return stubber - to select a method for stubbing
+ */
+ public static PowerMockitoStubber doReturn(Object toBeReturned) {
+ return POWERMOCKITO_CORE.doAnswer(new Returns(toBeReturned));
+ }
+
+ public static PowerMockitoStubber doReturn(Object toBeReturned, Object... othersToBeReturned) {
+ if (othersToBeReturned != null && othersToBeReturned.length == 0) {
+ return doReturn(toBeReturned);
+ }
+ return POWERMOCKITO_CORE.doAnswer(new ChainReturns(toBeReturned, othersToBeReturned));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java
new file mode 100644
index 0000000..bd6abaa
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/ConstructorExpectationSetup.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface ConstructorExpectationSetup<T> extends WithOrWithoutExpectedArguments<T>, WithExpectedParameterTypes<T>, WithAnyArguments<T> {
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java
new file mode 100644
index 0000000..39a03d9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PowerMockitoStubber.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.Mockito;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.Stubber;
+
+import java.lang.reflect.Method;
+
+/**
+ * Setup stubbing for private or void methods in final class, final void
+ * methods, or static (final) methods.
+ */
+public interface PowerMockitoStubber extends Stubber {
+ /**
+ * Allows to choose a static method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(StaticList.class);
+ * StaticList.clear();
+ *
+ * //following throws RuntimeException:
+ * StaticList.clear();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ void when(Class<?> classMock);
+
+ /**
+ * Allows to mock a private instance method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, method("myMethod")).withNoArguments();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception;
+
+ /**
+ * Allows to mock a private instance method based on the parameters when
+ * stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(T mock, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a private instance method based on method name and
+ * parameters when stubbing in doThrow()|doAnswer()|doNothing()|doReturn()
+ * style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(instance, "methodName", parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(T mock, String methodToExpect, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a static private method when stubbing in
+ * doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, method("myMethod")).withNoArguments();
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception;
+
+ /**
+ * Allows to mock a static private method based on the parameters when
+ * stubbing in doThrow()|doAnswer()|doNothing()|doReturn() style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(Class<T> classMock, Object... arguments) throws Exception;
+
+ /**
+ * Allows to mock a static private method based on method name and
+ * parameters when stubbing in doThrow()|doAnswer()|doNothing()|doReturn()
+ * style.
+ * <p>
+ * Example:
+ *
+ * <pre>
+ * doThrow(new RuntimeException()).when(MyClass.class, "methodName", parameter1, parameter2);
+ * </pre>
+ *
+ * Read more about those methods:
+ * <p>
+ * {@link Mockito#doThrow(Throwable)}
+ * <p>
+ * {@link Mockito#doAnswer(Answer)}
+ * <p>
+ * {@link Mockito#doNothing()}
+ * <p>
+ * {@link Mockito#doReturn(Object)}
+ * <p>
+ *
+ * See examples in javadoc for {@link Mockito}
+ */
+ <T> void when(Class<T> classMock, String methodToExpect, Object... parameters) throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java
new file mode 100644
index 0000000..da4c69a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/PrivatelyExpectedArguments.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */package org.powermock.api.mockito.expectation;
+
+public interface PrivatelyExpectedArguments {
+ <T> void withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+ <T> void withNoArguments() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java
new file mode 100644
index 0000000..cb1bd6b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithAnyArguments.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithAnyArguments<T> {
+
+ OngoingStubbing<T> withAnyArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java
new file mode 100644
index 0000000..3402346
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedArguments.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithExpectedArguments<T> {
+
+ OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java
new file mode 100644
index 0000000..500d062
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithExpectedParameterTypes.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface WithExpectedParameterTypes<T> {
+
+ WithExpectedArguments<T> withParameterTypes(Class<?> parameterType, Class<?>... additionalParameterTypes);
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java
new file mode 100644
index 0000000..4947186
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithOrWithoutExpectedArguments.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+public interface WithOrWithoutExpectedArguments<T> extends WithExpectedArguments<T>, WithoutExpectedArguments<T> {
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java
new file mode 100644
index 0000000..eabf878
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/expectation/WithoutExpectedArguments.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+
+public interface WithoutExpectedArguments<T> {
+
+ OngoingStubbing<T> withNoArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java
new file mode 100644
index 0000000..50f0661
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/PowerMockitoCore.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal;
+
+import org.mockito.Mockito;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.stubbing.Answer;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.internal.expectation.PowerMockitoStubberImpl;
+import org.powermock.api.mockito.internal.verification.StaticMockAwareVerificationMode;
+import org.powermock.reflect.Whitebox;
+
+public class PowerMockitoCore {
+ @SuppressWarnings("rawtypes")
+ public PowerMockitoStubber doAnswer(Answer answer) {
+ // We change the context classloader to the current CL in order for the Mockito
+ // framework to load it's plugins (such as MockMaker) correctly.
+ final ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ try {
+ getMockingProgress().stubbingStarted();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCL);
+ }
+ getMockingProgress().resetOngoingStubbing();
+ return (PowerMockitoStubber) new PowerMockitoStubberImpl().doAnswer(answer);
+ }
+
+ private MockingProgress getMockingProgress() {
+ return Whitebox.getInternalState(Mockito.class, MockingProgress.class);
+ }
+
+ public MockAwareVerificationMode wrapInMockitoSpecificVerificationMode(Object mock, VerificationMode mode) {
+ return new MockAwareVerificationMode(mock, mode);
+ }
+
+ public MockAwareVerificationMode wrapInStaticVerificationMode(VerificationMode mode) {
+ return new StaticMockAwareVerificationMode(mode);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java
new file mode 100644
index 0000000..2e71df9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoInjectingAnnotationEngine.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.configuration;
+
+import org.mockito.Mock;
+import org.mockito.internal.configuration.InjectingAnnotationEngine;
+
+/**
+ * The same as {@link InjectingAnnotationEngine} with the exception that it
+ * doesn't create/injects mocks annotated with the standard annotations such as
+ * {@link Mock}.
+ */
+public class PowerMockitoInjectingAnnotationEngine extends InjectingAnnotationEngine {
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void process(Class<?> context, Object testClass) {
+ // this will create @Spies:
+ new PowerMockitoSpyAnnotationEngine().process(context, testClass);
+
+ // this injects mocks
+ injectMocks(testClass);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java
new file mode 100644
index 0000000..9e2fa40
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/configuration/PowerMockitoSpyAnnotationEngine.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.configuration;
+
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.configuration.SpyAnnotationEngine;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Field;
+
+/**
+ * More or less a copy of the {@link SpyAnnotationEngine} but it uses
+ * {@link PowerMockito#spy(Object)} instead.
+ */
+public class PowerMockitoSpyAnnotationEngine extends SpyAnnotationEngine {
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void process(Class<?> context, Object testClass) {
+ Field[] fields = context.getDeclaredFields();
+ for (Field field : fields) {
+ if (field.isAnnotationPresent(Spy.class)) {
+ try {
+ Whitebox.invokeMethod(this, Spy.class, field, new Class<?>[] { Mock.class,
+ org.mockito.MockitoAnnotations.Mock.class, Captor.class });
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e1) {
+ throw new RuntimeException(e1);
+ }
+ boolean wasAccessible = field.isAccessible();
+ field.setAccessible(true);
+ try {
+ Object instance = field.get(testClass);
+ if (instance == null) {
+ throw new MockitoException("Cannot create a @Spy for '" + field.getName()
+ + "' field because the *instance* is missing\n" + "Example of correct usage of @Spy:\n"
+ + " @Spy List mock = new LinkedList();\n");
+ }
+ field.set(testClass, PowerMockito.spy(instance));
+ } catch (IllegalAccessException e) {
+ throw new MockitoException("Problems initiating spied field " + field.getName(), e);
+ } finally {
+ field.setAccessible(wasAccessible);
+ }
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java
new file mode 100644
index 0000000..bd42042
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/exceptions/StackTraceCleanerProvider.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.exceptions;
+
+import org.mockito.exceptions.stacktrace.StackTraceCleaner;
+
+public class StackTraceCleanerProvider implements org.mockito.plugins.StackTraceCleanerProvider {
+ @Override
+ public StackTraceCleaner getStackTraceCleaner(final StackTraceCleaner defaultCleaner) {
+ return new StackTraceCleaner() {
+ @Override
+ public boolean isOut(StackTraceElement candidate) {
+ return defaultCleaner.isOut(candidate) || candidate.getClassName().startsWith("org.powermock.api.mockito");
+ }
+ };
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java
new file mode 100644
index 0000000..3f94a09
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/ConstructorAwareExpectationSetup.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+
+import java.lang.reflect.Constructor;
+
+public class ConstructorAwareExpectationSetup<T> implements WithOrWithoutExpectedArguments<T> {
+
+ private final Constructor<T> ctor;
+
+ public ConstructorAwareExpectationSetup(Constructor<T> ctor) {
+ if (ctor == null) {
+ throw new IllegalArgumentException("Constructor to expect cannot be null");
+ }
+ this.ctor = ctor;
+ }
+
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ return setupExpectation().withArguments(firstArgument, additionalArguments);
+ }
+
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return setupExpectation().withNoArguments();
+ }
+
+ private DefaultConstructorExpectationSetup<T> setupExpectation() {
+ DefaultConstructorExpectationSetup<T> setup = new DefaultConstructorExpectationSetup<T>(ctor.getDeclaringClass());
+ setup.setParameterTypes(ctor.getParameterTypes());
+ return setup;
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java
new file mode 100644
index 0000000..9cffa79
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultConstructorExpectationSetup.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Matchers;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.ConstructorExpectationSetup;
+import org.powermock.api.mockito.expectation.WithExpectedArguments;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.api.mockito.internal.mockcreation.MockCreator;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.tests.utils.ArrayMerger;
+import org.powermock.tests.utils.impl.ArrayMergerImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class DefaultConstructorExpectationSetup<T> implements ConstructorExpectationSetup<T> {
+
+ private final Class<T> mockType;
+ private final ArrayMerger arrayMerger;
+ private Class<?>[] parameterTypes = null;
+
+ public DefaultConstructorExpectationSetup(Class<T> mockType) {
+ this.mockType = mockType;
+ arrayMerger = new ArrayMergerImpl();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static <T> OngoingStubbing<T> createNewSubstituteMock(Class<T> type, Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ if (type == null) {
+ throw new IllegalArgumentException("type cannot be null");
+ }
+
+ final Class<T> unmockedType = (Class<T>) WhiteboxImpl.getUnmockedType(type);
+ if (parameterTypes == null) {
+ WhiteboxImpl.findUniqueConstructorOrThrowException(type, arguments);
+ } else {
+ WhiteboxImpl.getConstructor(unmockedType, parameterTypes);
+ }
+
+ /*
+ * Check if this type has been mocked before
+ */
+ NewInvocationControl<OngoingStubbing<T>> newInvocationControl = (NewInvocationControl<OngoingStubbing<T>>) MockRepository
+ .getNewInstanceControl(unmockedType);
+ if (newInvocationControl == null) {
+ InvocationSubstitute<T> mock = MockCreator.mock(InvocationSubstitute.class, false, false, null, null, (Method[]) null);
+ newInvocationControl = new MockitoNewInvocationControl(mock);
+ MockRepository.putNewInstanceControl(type, newInvocationControl);
+ MockRepository.addObjectsToAutomaticallyReplayAndVerify(WhiteboxImpl.getUnmockedType(type));
+ }
+
+ return newInvocationControl.expectSubstitutionLogic(arguments);
+ }
+
+ void setParameterTypes(Class<?>[] parameterTypes) {
+ this.parameterTypes = parameterTypes;
+ }
+
+ OngoingStubbing<T> withArguments(Object[] additionalArguments) throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, additionalArguments);
+ }
+
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, arrayMerger.mergeArrays(Object.class, new Object[]{firstArgument},
+ additionalArguments));
+ }
+
+ @Override
+ public OngoingStubbing<T> withAnyArguments() throws Exception {
+ if (mockType == null) {
+ throw new IllegalArgumentException("Class to expected cannot be null");
+ }
+ final Class<T> unmockedType = (Class<T>) WhiteboxImpl.getUnmockedType(mockType);
+ final Constructor<?>[] allConstructors = WhiteboxImpl.getAllConstructors(unmockedType);
+ final Constructor<?> constructor = allConstructors[0];
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ Object[] paramArgs = new Object[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Class<?> paramType = parameterTypes[i];
+ paramArgs[i] = Matchers.any(paramType);
+ }
+ final OngoingStubbing<T> ongoingStubbing = createNewSubstituteMock(mockType, parameterTypes, paramArgs);
+ Constructor<?>[] otherCtors = new Constructor<?>[allConstructors.length-1];
+ System.arraycopy(allConstructors, 1, otherCtors, 0, allConstructors.length-1);
+ return new DelegatingToConstructorsOngoingStubbing<T>(otherCtors, ongoingStubbing);
+ }
+
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return createNewSubstituteMock(mockType, parameterTypes, new Object[0]);
+ }
+
+ @Override
+ public WithExpectedArguments<T> withParameterTypes(Class<?> parameterType, Class<?>... additionalParameterTypes) {
+ this.parameterTypes = arrayMerger.mergeArrays(Class.class, new Class<?>[] { parameterType }, additionalParameterTypes);
+ return this;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java
new file mode 100644
index 0000000..7fc722f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetup.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Mockito;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.api.mockito.expectation.WithOrWithoutExpectedArguments;
+
+import java.lang.reflect.Method;
+
+public class DefaultMethodExpectationSetup<T> implements WithOrWithoutExpectedArguments<T> {
+
+ private final Object object;
+
+ private final Method method;
+
+ public DefaultMethodExpectationSetup(Object object, Method method) {
+ if (object == null) {
+ throw new IllegalArgumentException("object to expect cannot be null");
+ } else if (method == null) {
+ throw new IllegalArgumentException("method to expect cannot be null");
+ }
+ this.object = object;
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ private static Object[] join(Object o, Object[] array) {
+ Object[] res = new Object[array.length + 1];
+ res[0] = o;
+ System.arraycopy(array, 0, res, 1, array.length);
+ return res;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public OngoingStubbing<T> withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object, firstArgument));
+ } else {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object, join(firstArgument, additionalArguments)));
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public OngoingStubbing<T> withNoArguments() throws Exception {
+ return (OngoingStubbing<T>) Mockito.when(method.invoke(object));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java
new file mode 100644
index 0000000..1cd470b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DefaultPrivatelyExpectedArguments.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.powermock.api.mockito.expectation.PrivatelyExpectedArguments;
+
+import java.lang.reflect.Method;
+
+public class DefaultPrivatelyExpectedArguments implements PrivatelyExpectedArguments {
+
+ private final Method method;
+ private final Object mock;
+
+ public DefaultPrivatelyExpectedArguments(Object mock, Method method) {
+ this.mock = mock;
+ this.method = method;
+ method.setAccessible(true);
+ }
+
+ @Override
+ public <T> void withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ method.invoke(mock, firstArgument);
+ } else {
+ Object[] allArgs = new Object[additionalArguments.length + 1];
+ allArgs[0] = firstArgument;
+ if (additionalArguments.length > 0) {
+ System.arraycopy(additionalArguments, 0, allArgs, 1, additionalArguments.length);
+ }
+ method.invoke(mock, allArgs);
+ }
+ }
+
+ @Override
+ public <T> void withNoArguments() throws Exception {
+ method.invoke(mock);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java
new file mode 100644
index 0000000..42090b7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/DelegatingToConstructorsOngoingStubbing.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.Matchers;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.core.spi.support.InvocationSubstitute;
+
+import java.lang.reflect.Constructor;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * Implementation of OngoingStubbing that delegates invocations to all supplied ctors
+ * @param <T>
+ */
+public class DelegatingToConstructorsOngoingStubbing<T> implements OngoingStubbing<T>{
+
+ private final OngoingStubbing<T> stubbing;
+ private final Constructor<?>[] ctors;
+
+ public DelegatingToConstructorsOngoingStubbing(Constructor<?>[] ctors, OngoingStubbing<T> stubbing) {
+ if(stubbing == null) {
+ throw new IllegalArgumentException("Internal error: Ongoing stubbing must be provided");
+ }
+ this.ctors = ctors;
+ this.stubbing = stubbing;
+ }
+
+ @Override
+ public OngoingStubbing<T> thenReturn(final T value) {
+ stubbing.thenReturn(value);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenReturn(value);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenReturn(final T value, final T... values) {
+ stubbing.thenReturn(value, values);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenReturn(value, values);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenThrow(final Throwable... throwables) {
+ stubbing.thenThrow(throwables);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenThrow(throwables);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenThrow(final Class<? extends Throwable> throwableType) {
+ stubbing.thenThrow(throwableType);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenThrow(throwableType);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenThrow(final Class<? extends Throwable> toBeThrown, final Class<? extends Throwable>... nextToBeThrown) {
+ stubbing.thenThrow(toBeThrown, nextToBeThrown);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenThrow(toBeThrown,nextToBeThrown);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenCallRealMethod() {
+ stubbing.thenCallRealMethod();
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenCallRealMethod();
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> thenAnswer(final Answer<?> answer) {
+ stubbing.thenAnswer(answer);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.thenAnswer(answer);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public OngoingStubbing<T> then(final Answer<?> answer) {
+ stubbing.then(answer);
+ return new InvokeStubMethod() {
+ @Override
+ public void performStubbing(OngoingStubbing<T> when) {
+ when.then(answer);
+ }
+ }.invoke();
+ }
+
+ @Override
+ public <M> M getMock() {
+ return stubbing.getMock();
+ }
+
+
+ private abstract class InvokeStubMethod {
+ public OngoingStubbing<T> invoke() {
+ final InvocationSubstitute<T> mock = stubbing.getMock();
+ for (Constructor<?> constructor : ctors) {
+ final Class<?>[] parameterTypesForCtor = constructor.getParameterTypes();
+ Object[] paramArgs = new Object[parameterTypesForCtor.length];
+ for (int i = 0; i < parameterTypesForCtor.length; i++) {
+ Class<?> paramType = parameterTypesForCtor[i];
+ paramArgs[i] = Matchers.any(paramType);
+ }
+ try {
+ final OngoingStubbing<T> when = when(mock.performSubstitutionLogic(paramArgs));
+ performStubbing(when);
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error",e);
+ }
+ }
+
+ return stubbing;
+ }
+
+ public abstract void performStubbing(OngoingStubbing<T> when);
+
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java
new file mode 100644
index 0000000..310d409
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/expectation/PowerMockitoStubberImpl.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.mockito.internal.stubbing.StubberImpl;
+import org.mockito.invocation.MockHandler;
+import org.mockito.stubbing.Stubber;
+import org.powermock.api.mockito.expectation.PowerMockitoStubber;
+import org.powermock.api.mockito.expectation.PrivatelyExpectedArguments;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Extension of the standard Mocktio stubber implementation that also support
+ * PowerMockito created mocks.
+ */
+public class PowerMockitoStubberImpl extends StubberImpl implements PowerMockitoStubber {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void when(Class<?> classMock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getStaticMethodInvocationControl(classMock);
+ addAnswersForStubbing(invocationControl);
+ }
+
+ /**
+ * Supports PowerMockito mocks. If <code>mock</code> is not a PowerMockito
+ * mock it will delegate to Mockito.
+ *
+ * @see Stubber#when(Object)
+ */
+ @Override
+ public <T> T when(T instanceMock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getInstanceMethodInvocationControl(instanceMock);
+ final T returnValue;
+ if (invocationControl == null) {
+ returnValue = super.when(instanceMock);
+ } else {
+ addAnswersForStubbing(invocationControl);
+ returnValue = instanceMock;
+ }
+ return returnValue;
+ }
+
+ @SuppressWarnings("unchecked")
+ private void addAnswersForStubbing(MockitoMethodInvocationControl invocationControl) {
+ final MockHandler mockHandler = invocationControl.getInvocationHandler().getHandler();
+ final List list = Whitebox.getInternalState(this, List.class);
+ try {
+ Whitebox.invokeMethod(mockHandler, "setAnswersForStubbing", list);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public <T> PrivatelyExpectedArguments when(T mock, Method method) throws Exception {
+ assertNotNull(mock, "mock");
+ assertNotNull(method, "Method");
+ prepareForStubbing(mock);
+ return new DefaultPrivatelyExpectedArguments(mock, method);
+ }
+
+ @Override
+ public <T> void when(T mock, Object... arguments) throws Exception {
+ assertNotNull(mock, "mock");
+ prepareForStubbing(mock);
+ Whitebox.invokeMethod(mock, arguments);
+ }
+
+ @Override
+ public <T> void when(T mock, String methodToExpect, Object... arguments) throws Exception {
+ assertNotNull(mock, "mock");
+ assertNotNull(methodToExpect, "methodToExpect");
+ prepareForStubbing(mock);
+ Whitebox.invokeMethod(mock, methodToExpect, arguments);
+ }
+
+ @Override
+ public <T> void when(Class<T> classMock, Object... arguments) throws Exception {
+ assertNotNull(classMock, "classMock");
+ when(classMock);
+ Whitebox.invokeMethod(classMock, arguments);
+ }
+
+ @Override
+ public <T> void when(Class<T> classMock, String methodToExpect, Object... parameters) throws Exception {
+ assertNotNull(classMock, "classMock");
+ assertNotNull(methodToExpect, "methodToExpect");
+ when(classMock);
+ Whitebox.invokeMethod(classMock, methodToExpect, parameters);
+ }
+
+ @Override
+ public <T> PrivatelyExpectedArguments when(Class<T> classMock, Method method) throws Exception {
+ assertNotNull(classMock, "classMock");
+ assertNotNull(method, "Method");
+ when(classMock);
+ return new DefaultPrivatelyExpectedArguments(classMock, method);
+ }
+
+ private void assertNotNull(Object object, String name) {
+ if (object == null) {
+ throw new IllegalArgumentException(name + " cannot be null");
+ }
+ }
+
+ private <T> void prepareForStubbing(T mock) {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository.getInstanceMethodInvocationControl(mock);
+ addAnswersForStubbing(invocationControl);
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java
new file mode 100644
index 0000000..c9e3010
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/InvocationControlAssertionError.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.Whitebox;
+
+import java.util.regex.Matcher;
+
+public class InvocationControlAssertionError {
+ private static final String AT = "at";
+ private static final String ERROR_LOCATION_MARKER = "->";
+ private static final String COLON_NEWLINE = ":\n";
+ private static final String HERE_TEXT = "here:\n";
+ private static final String UNDESIRED_INVOCATION_TEXT = " Undesired invocation:";
+
+ public static void updateErrorMessageForVerifyNoMoreInteractions(AssertionError errorToUpdate) {
+ /*
+ * VerifyNoMoreInteractions failed, we need to update the error message.
+ */
+ String verifyNoMoreInteractionsInvocation = null;
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ for (int i = stackTrace.length - 1; i >= 0; i--) {
+ final StackTraceElement stackTraceElement = stackTrace[i];
+ if (stackTraceElement.getClassName().equals(PowerMockito.class.getName())
+ && stackTraceElement.getMethodName().equals("verifyNoMoreInteractions")) {
+ final int invocationStackTraceIndex;
+ if (stackTrace[i + 1].getClassName().equals(PowerMockito.class.getName())
+ && stackTrace[i + 1].getMethodName().equals("verifyZeroInteractions")) {
+ invocationStackTraceIndex = i + 2;
+ } else {
+ invocationStackTraceIndex = i + 1;
+ }
+ verifyNoMoreInteractionsInvocation = stackTrace[invocationStackTraceIndex].toString();
+ }
+ }
+
+ if (verifyNoMoreInteractionsInvocation == null) {
+ // Something unexpected happened, just return
+ return;
+ }
+ String message = errorToUpdate.getMessage();
+ StringBuilder builder = new StringBuilder();
+ builder.append(message);
+ final int indexOfFirstAt = message.indexOf(AT);
+ final int startOfVerifyNoMoreInteractionsInvocation = indexOfFirstAt + AT.length() + 1;
+ final int endOfVerifyNoMoreInteractionsInvocation = message.indexOf('\n', indexOfFirstAt + AT.length());
+ builder.replace(startOfVerifyNoMoreInteractionsInvocation, endOfVerifyNoMoreInteractionsInvocation,
+ verifyNoMoreInteractionsInvocation);
+ builder.delete(builder.indexOf("\n", endOfVerifyNoMoreInteractionsInvocation + 1), builder.lastIndexOf("\n"));
+ Whitebox.setInternalState(errorToUpdate, builder.toString());
+ }
+
+ public static void updateErrorMessageForMethodInvocation(AssertionError errorToUpdate) {
+ /*
+ * We failed to verify the new substitution mock. This happens when, for
+ * example, the user has done something like
+ * whenNew(MyClass.class).thenReturn(myMock).times(3) when in fact an
+ * instance of MyClass has been created less or more times than 3.
+ */
+ Whitebox.setInternalState(errorToUpdate, "\n" + changeMessageContent(errorToUpdate.getMessage()));
+ }
+
+ public static void throwAssertionErrorForNewSubstitutionFailure(AssertionError oldError, Class<?> type) {
+ /*
+ * We failed to verify the new substitution mock. This happens when, for
+ * example, the user has done something like
+ * whenNew(MyClass.class).thenReturn(myMock).times(3) when in fact an
+ * instance of MyClass has been created less or more times than 3.
+ */
+ final String newSubsitutionClassName = InvocationSubstitute.class.getSimpleName();
+ final String newSubsitutionClassNameInMockito = newSubsitutionClassName.substring(0, 1).toLowerCase()
+ + newSubsitutionClassName.substring(1);
+ String message = oldError.getMessage();
+ final String newSubsitutionMethodName = InvocationSubstitute.class.getDeclaredMethods()[0].getName();
+ message = message.replaceAll(newSubsitutionClassNameInMockito + "." + newSubsitutionMethodName, Matcher
+ .quoteReplacement(type.getName()));
+ message = message.replaceAll("method", "constructor");
+ throw new AssertionError(changeMessageContent(message));
+ }
+
+ private static String changeMessageContent(String message) {
+ /*
+ * Temp fix: Remove powermock internal "at locations" (points to which
+ * line the expectation went wrong in Mockito). We should try to find
+ * the real ones instead
+ */
+ StringBuilder builder = removeFailureLocations(message);
+ // Remove "Undesired invocation:"
+ removeText(builder, UNDESIRED_INVOCATION_TEXT);
+
+ removeAndReplaceText(builder, HERE_TEXT, ' ');
+
+ removeAndReplaceText(builder, COLON_NEWLINE, ' ');
+ final String finalMessage = builder.toString().trim();
+ return finalMessage;
+ }
+
+ private static StringBuilder removeFailureLocations(String message) {
+ StringBuilder builder = new StringBuilder();
+ builder.append(message);
+ int indexOfBeginLocation = builder.indexOf(ERROR_LOCATION_MARKER);
+ while (indexOfBeginLocation > 0) {
+ int indexOfLocationEnd = builder.indexOf("\n", indexOfBeginLocation);
+ builder.delete(indexOfBeginLocation, indexOfLocationEnd < 0 ? builder.length() : indexOfLocationEnd + 1);
+ indexOfBeginLocation = builder.indexOf(ERROR_LOCATION_MARKER);
+ }
+ return builder;
+ }
+
+ private static void removeAndReplaceText(StringBuilder builder, String text, char appender) {
+ int currentTextIndex = builder.indexOf(text);
+ int previousTextIndex = 0;
+ boolean isSingleConcat = true;
+ while (currentTextIndex > 0) {
+ previousTextIndex = currentTextIndex;
+ builder.delete(currentTextIndex, currentTextIndex + text.length());
+ currentTextIndex = builder.indexOf(text);
+ if (isLastFinding(currentTextIndex) && !isSingleConcat) {
+ builder.replace(builder.length(), builder.length(), ".");
+ } else {
+ builder.replace(previousTextIndex, previousTextIndex + 1, String.valueOf(
+ builder.charAt(previousTextIndex)).toLowerCase());
+ builder.insert(previousTextIndex, String.valueOf(appender));
+ currentTextIndex++;
+ isSingleConcat = false;
+ }
+ }
+ }
+
+ private static boolean isLastFinding(int index) {
+ return index < 0;
+ }
+
+ private static void removeText(StringBuilder builder, String text) {
+ int textIndex = builder.indexOf(text);
+ while (textIndex > 0) {
+ builder.delete(textIndex, textIndex + text.length());
+ textIndex = builder.indexOf(text);
+ }
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java
new file mode 100644
index 0000000..4ec9bd1
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoMethodInvocationControl.java
@@ -0,0 +1,339 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.misusing.NotAMockException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.debugging.Localized;
+import org.mockito.internal.exceptions.stacktrace.StackTraceFilter;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
+import org.mockito.internal.invocation.realmethod.RealMethod;
+import org.mockito.internal.progress.MockingProgress;
+import org.mockito.internal.progress.SequenceNumber;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.verification.VerificationDataImpl;
+import org.mockito.internal.verification.VerificationModeFactory;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.verification.VerificationMode;
+import org.powermock.api.mockito.internal.verification.StaticMockAwareVerificationMode;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+import org.powermock.api.support.SafeExceptionRethrower;
+import org.powermock.core.MockGateway;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A Mockito implementation of the {@link MethodInvocationControl} interface.
+ */
+public class MockitoMethodInvocationControl implements MethodInvocationControl {
+
+ private final MethodInterceptorFilter methodInterceptorFilter;
+
+ private final Set<Method> mockedMethods;
+ private final Object delegator;
+ private final Object mockInstance;
+
+ /**
+ * Creates a new instance.
+ *
+ * @param methodInterceptionFilter
+ * The methodInterceptionFilter to be associated with this
+ * instance.
+ * @param mockInstance
+ * The actual mock instance. May be <code>null</code>. Even
+ * though the mock instance may not be used it's needed to keep a
+ * reference to this object otherwise it may be garbage collected
+ * in some situations. For example when mocking static methods we
+ * don't return the mock object and thus it will be garbage
+ * collected (and thus the finalize method will be invoked which
+ * will be caught by the proxy and the test will fail because we
+ * haven't setup expectations for this method) because then that
+ * object has no reference. In order to avoid this we keep a
+ * reference to this instance here.
+ * @param methodsToMock
+ * The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null or empty, all methods for
+ * the <code>invocationHandler</code> are considered to be
+ * mocked.
+ */
+ public MockitoMethodInvocationControl(MethodInterceptorFilter methodInterceptionFilter, Object mockInstance, Method... methodsToMock) {
+ this(methodInterceptionFilter, null, mockInstance, methodsToMock);
+ }
+
+ /**
+ * Creates a new instance with a delegator. This delegator may be
+ * <code>null</code> (if it is then no calls will be forwarded to this
+ * instance). If a delegator exists (i.e. not null) all non-mocked calls
+ * will be delegated to that instance.
+ * @param methodInterceptionFilter
+ * The methodInterceptionFilter to be associated with this
+ * instance.
+ * @param delegator
+ * If the user spies on an instance the original instance must be
+ * injected here.
+ * @param mockInstance
+ * The actual mock instance. May be <code>null</code>. Even
+ * though the mock instance may not be used it's needed to keep a
+ * reference to this object otherwise it may be garbage collected
+ * in some situations. For example when mocking static methods we
+ * don't return the mock object and thus it will be garbage
+ * collected (and thus the finalize method will be invoked which
+ * will be caught by the proxy and the test will fail because we
+ * haven't setup expectations for this method) because then that
+ * object has no reference. In order to avoid this we keep a
+ * reference to this instance here.
+ * @param methodsToMock
+ * The methods that are mocked for this instance. If
+ * <code>methodsToMock</code> is null or empty, all methods for
+ * the <code>invocationHandler</code> are considered to be
+ */
+ public MockitoMethodInvocationControl(MethodInterceptorFilter methodInterceptionFilter, Object delegator,
+ Object mockInstance, Method... methodsToMock) {
+ if (methodInterceptionFilter == null) {
+ throw new IllegalArgumentException("Invocation Handler cannot be null.");
+ }
+
+ this.mockedMethods = toSet(methodsToMock);
+ this.mockInstance = mockInstance;
+ this.delegator = delegator;
+ this.methodInterceptorFilter = methodInterceptionFilter;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean isMocked(Method method) {
+ return mockedMethods == null || (mockedMethods != null && mockedMethods.contains(method));
+ }
+
+ private boolean isInVerificationMode() {
+ return getVerificationMode() != null;
+ }
+
+ private VerificationMode getVerificationMode() {
+ try {
+ MockingProgress progress = (MockingProgress) Whitebox.invokeMethod(ThreadSafeMockingProgress.class,
+ "threadSafely");
+ return getVerificationModeFromMockProgress(progress);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private VerificationMode getVerificationModeFromMockProgress(MockingProgress mockingProgress) {
+ if (mockingProgress == null) {
+ return null;
+ }
+ if (mockingProgress instanceof ThreadSafeMockingProgress) {
+ ThreadLocal<MockingProgress> threadLocal = Whitebox.getInternalState(mockingProgress, ThreadLocal.class);
+ return getVerificationModeFromMockProgress(threadLocal.get());
+ } else {
+ Localized<VerificationMode> verificationMode = Whitebox.getInternalState(mockingProgress, Localized.class);
+ return verificationMode == null ? null : verificationMode.getObject();
+ }
+ }
+
+ @Override
+ public Object invoke(final Object obj, final Method method, final Object[] arguments) throws Throwable {
+ /*
+ * If we come here and it means that the class has been modified by
+ * PowerMock. If this handler has a delegator (i.e. is in spy mode in
+ * the current implementation) and it has been caught by the Mockito
+ * proxy before our Mockgateway we need to know if the method is private
+ * or not. Because if the previously described preconditions are met and
+ * the method is not private it means that Mockito has already processed
+ * the method invocation and we should NOT delegate the call to Mockito
+ * again (thus we return proceed). If we would do that Mockito will
+ * receive multiple method invocations to proxy for each method
+ * invocation. For privately spied methods Mockito haven't received the
+ * invocation and thus we should delegate the call to the Mockito proxy.
+ */
+ final Object returnValue;
+ final int methodModifiers = method.getModifiers();
+ if (hasDelegator() && !Modifier.isPrivate(methodModifiers) && !Modifier.isFinal(methodModifiers)
+ && !Modifier.isStatic(methodModifiers) && hasBeenCaughtByMockitoProxy()) {
+ returnValue = MockGateway.PROCEED;
+ } else {
+ boolean inVerificationMode = isInVerificationMode();
+ if (WhiteboxImpl.isClass(obj) && inVerificationMode) {
+ handleStaticVerification((Class<?>) obj);
+ }
+ returnValue = performIntercept(methodInterceptorFilter, obj, method, arguments);
+ if (returnValue == null) {
+ return MockGateway.SUPPRESS;
+ }
+ }
+ return returnValue;
+ }
+
+ private void handleStaticVerification(Class<?> cls) {
+ VerificationMode verificationMode = getVerificationMode();
+ if (verificationMode instanceof StaticMockAwareVerificationMode) {
+ ((StaticMockAwareVerificationMode) verificationMode).setClassMock(cls);
+ }
+ }
+
+ private boolean hasBeenCaughtByMockitoProxy() {
+ StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+ StackTraceFilter filter = new StackTraceFilter();
+ /*
+ * We filter the stack-trace to check if "Mockito" exists as a stack trace element. (The filter method
+ * remove all Mocktio stack trace elements). If the filtered stack trace length is not equal to the original stack trace length
+ * this means that the call has been caught by Mockito.
+ */
+ final StackTraceElement[] filteredStackTrace = filter.filter(stackTrace, true);
+ return filteredStackTrace.length != stackTrace.length;
+ }
+
+ private Object performIntercept(MethodInterceptorFilter invocationHandler, final Object interceptionObject,
+ final Method method, Object[] arguments) throws Throwable {
+ MockHandler mockHandler = invocationHandler.getHandler();
+
+ final CleanTraceRealMethod cglibProxyRealMethod = new CleanTraceRealMethod(new RealMethod() {
+ private static final long serialVersionUID = 4564320968038564170L;
+
+ @Override
+ public Object invoke(Object target, Object[] arguments) throws Throwable {
+ /*
+ * Instruct the MockGateway to don't intercept the next call.
+ * The reason is that when Mockito is spying on objects it
+ * should call the "real method" (which is proxied by Mockito
+ * anyways) so that we don't end up in here one more time which
+ * causes infinite recursion. This should not be done if the
+ * interceptionObject is a final system class because these are
+ * never caught by the Mockito proxy.
+ */
+ final Class<?> type = Whitebox.getType(interceptionObject);
+ final boolean isFinalSystemClass = type.getName().startsWith("java.") && Modifier.isFinal(type.getModifiers());
+ if (!isFinalSystemClass) {
+ MockRepository.putAdditionalState(MockGateway.DONT_MOCK_NEXT_CALL, true);
+ }
+ try {
+ return method.invoke(target, arguments);
+ } catch (InvocationTargetException e) {
+ SafeExceptionRethrower.safeRethrow(e.getCause());
+ }
+ return null;
+ }
+ });
+
+ Invocation invocation = new InvocationImpl(
+ interceptionObject,
+ new DelegatingMethod(method),
+ arguments,
+ SequenceNumber.next(),
+ cglibProxyRealMethod) {
+ private static final long serialVersionUID = -3679957412502758558L;
+
+ @Override
+ public String toString() {
+ return new ToStringGenerator().generate(getMock(), getMethod(), getArguments());
+ }
+ };
+
+ try {
+ return replaceMatchersBinderIfNeeded(mockHandler).handle(invocation);
+ } catch (NotAMockException e) {
+ if(invocation.getMock().getClass().getName().startsWith("java.") && MockRepository.getInstanceMethodInvocationControl(invocation.getMock()) != null) {
+ return invocation.callRealMethod();
+ } else {
+ throw e;
+ }
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForMethodInvocation(e);
+ throw e;
+ }
+ }
+
+ private MockHandler replaceMatchersBinderIfNeeded(MockHandler mockHandler) {
+ if(!Whitebox.getFieldsOfType(mockHandler, MatchersBinder.class).isEmpty()) {
+ Whitebox.setInternalState(mockHandler, new PowerMockMatchersBinder());
+ } else if(!Whitebox.getFieldsOfType(mockHandler, InternalMockHandler.class).isEmpty()) {
+ final MockHandler internalMockHandler = Whitebox.getInternalState(mockHandler, MockHandler.class);
+ return replaceMatchersBinderIfNeeded(internalMockHandler);
+ }
+ return mockHandler;
+ }
+
+ @Override
+ public Object replay(Object... mocks) {
+ throw new IllegalStateException("Internal error: No such thing as replay exists in Mockito.");
+ }
+
+ @Override
+ public Object reset(Object... mocks) {
+ throw new IllegalStateException("Internal error: No such thing as reset exists in Mockito.");
+ }
+
+ @Override
+ public Object verify(Object... mocks) {
+ if (mocks == null || mocks.length != 1) {
+ throw new IllegalArgumentException("Must supply one mock to the verify method.");
+ }
+ return Mockito.verify(mocks[0]);
+ }
+
+ public void verifyNoMoreInteractions() {
+ try {
+ final MockHandler mockHandler = methodInterceptorFilter.getHandler();
+ if (mockHandler instanceof MockHandler) {
+ InvocationContainer invocationContainer = Whitebox.<InvocationContainer>invokeMethod(mockHandler, "getInvocationContainer");
+ VerificationDataImpl data = new VerificationDataImpl(invocationContainer, null);
+ VerificationModeFactory.noMoreInteractions().verify(data);
+ } else {
+ throw new RuntimeException(
+ "Cannot perform verifyNoMoreInteractions because of unknown mockhandler type "
+ + mockHandler.getClass());
+ }
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForVerifyNoMoreInteractions(e);
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error",e);
+ }
+ }
+
+ private Set<Method> toSet(Method... methods) {
+ return methods == null ? null : new HashSet<Method>(Arrays.asList(methods));
+ }
+
+ private boolean hasDelegator() {
+ return delegator != null;
+ }
+
+ public MethodInterceptorFilter getInvocationHandler() {
+ return methodInterceptorFilter;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java
new file mode 100644
index 0000000..56be734
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/MockitoNewInvocationControl.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.stubbing.OngoingStubbing;
+import org.mockito.verification.VerificationMode;
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+
+import static org.mockito.Mockito.times;
+
+public class MockitoNewInvocationControl<T> implements NewInvocationControl<OngoingStubbing<T>> {
+ private final InvocationSubstitute<T> substitute;
+
+ public MockitoNewInvocationControl(InvocationSubstitute<T> substitute) {
+ if (substitute == null) {
+ throw new IllegalArgumentException("Internal error: substitute cannot be null.");
+ }
+ this.substitute = substitute;
+ }
+
+ @Override
+ public Object invoke(Class<?> type, Object[] args, Class<?>[] sig) throws Exception {
+ Constructor<?> constructor = WhiteboxImpl.getConstructor(type, sig);
+ if (constructor.isVarArgs()) {
+ Object varArgs = args[args.length - 1];
+ final int varArgsLength = Array.getLength(varArgs);
+ Object[] oldArgs = args;
+ args = new Object[args.length + varArgsLength - 1];
+ System.arraycopy(oldArgs, 0, args, 0, oldArgs.length - 1);
+ for (int i = oldArgs.length - 1, j=0; i < args.length; i++, j++) {
+ args[i] = Array.get(varArgs, j);
+ }
+ }
+ try {
+ return substitute.performSubstitutionLogic(args);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+
+ // Won't happen
+ return null;
+ }
+
+ @Override
+ public OngoingStubbing<T> expectSubstitutionLogic(Object... arguments) throws Exception {
+ return Mockito.when(substitute.performSubstitutionLogic(arguments));
+ }
+
+ public InvocationSubstitute<T> getSubstitute() {
+ return substitute;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object replay(Object... mocks) {
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized Object verify(Object... mocks) {
+ final VerificationMode verificationMode;
+ Object mode = MockRepository.getAdditionalState("VerificationMode");
+ if (mode != null) {
+ if (mode instanceof VerificationMode) {
+ verificationMode = (VerificationMode) mode;
+ } else {
+ throw new IllegalStateException("Internal error. VerificationMode in MockRepository was not of type "
+ + VerificationMode.class.getName() + ".");
+ }
+ } else {
+ verificationMode = times(1);
+ }
+ Mockito.verify(substitute, verificationMode);
+ return null;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public synchronized Object reset(Object... mocks) {
+ Mockito.<InvocationSubstitute<T>> reset(substitute);
+ return null;
+ }
+
+ public void verifyNoMoreInteractions() {
+ try {
+ Mockito.verifyNoMoreInteractions(substitute);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.updateErrorMessageForVerifyNoMoreInteractions(e);
+ throw e;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java
new file mode 100644
index 0000000..095fd4c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/PowerMockMatchersBinder.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.exceptions.Reporter;
+import org.mockito.internal.invocation.InvocationMatcher;
+import org.mockito.internal.invocation.MatchersBinder;
+import org.mockito.internal.matchers.LocalizedMatcher;
+import org.mockito.internal.progress.ArgumentMatcherStorage;
+import org.mockito.invocation.Invocation;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * This class is essentially a copy of {@link org.mockito.internal.invocation.MatchersBinder} with the exception that
+ * the InvocationMatcher is replaced and its toString method is overwritten to avoid exceptions. For why these exceptions happen
+ * refer to ToStringGenerator in this package.
+ */
+public class PowerMockMatchersBinder extends MatchersBinder {
+
+ public InvocationMatcher bindMatchers(ArgumentMatcherStorage argumentMatcherStorage, final Invocation invocation) {
+ List<LocalizedMatcher> lastMatchers = argumentMatcherStorage.pullLocalizedMatchers();
+ validateMatchers(invocation, lastMatchers);
+
+ // In Mockito 2.0 LocalizedMatcher no more extend ArgumentMatcher, so new list should be created.
+
+ final List<ArgumentMatcher> argumentMatchers = extractArgumentMatchers(lastMatchers);
+
+ final InvocationMatcher invocationWithMatchers = new InvocationMatcher(invocation, argumentMatchers) {
+ @Override
+ public String toString() {
+ return invocation.toString();
+ }
+ };
+
+ return invocationWithMatchers;
+ }
+
+ private List<ArgumentMatcher> extractArgumentMatchers(List<LocalizedMatcher> lastMatchers) {
+ final List<ArgumentMatcher> argumentMatchers = new ArrayList<ArgumentMatcher>(lastMatchers.size());
+
+ for (LocalizedMatcher localizedMatcher: lastMatchers){
+ argumentMatchers.add(localizedMatcher.getMatcher());
+ }
+ return argumentMatchers;
+ }
+
+ private void validateMatchers(Invocation invocation, List<LocalizedMatcher> lastMatchers) {
+ if (!lastMatchers.isEmpty()) {
+ int recordedMatchersSize = lastMatchers.size();
+ int expectedMatchersSize = invocation.getArguments().length;
+ if (expectedMatchersSize != recordedMatchersSize) {
+ new Reporter().invalidUseOfMatchers(expectedMatchersSize, lastMatchers);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java
new file mode 100644
index 0000000..4afc310
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/invocation/ToStringGenerator.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.invocation;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.internal.invocation.ArgumentsProcessor;
+import org.mockito.internal.matchers.text.MatchersPrinter;
+import org.mockito.internal.reporting.PrintSettings;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * We need to override the toString() in some classes because normally the toString
+ * "method" is assembled by calling the "qualifiedName" method but
+ * this is not possible in our case. The reason is that the
+ * qualifiedName method does
+ *
+ * <pre>
+ * new MockUtil().getMockName(mock)
+ * </pre>
+ *
+ * which later will call the "isMockitoMock" method which will
+ * return false and an exception will be thrown. The reason why
+ * "isMockitoMock" returns false is that the mock is not created by
+ * the Mockito CGLib Enhancer in case of static methods.
+ */
+public class ToStringGenerator {
+
+ public String generate(Object mock, Method method, Object[] arguments) {
+ final List<ArgumentMatcher> matcherList = ArgumentsProcessor.argumentsToMatchers(arguments);
+ final PrintSettings printSettings = new PrintSettings();
+ MatchersPrinter matchersPrinter = new MatchersPrinter();
+
+ String methodName = Whitebox.getType(mock).getName() + "." + method.getName();
+ String invocation = methodName + matchersPrinter.getArgumentsLine(matcherList, printSettings);
+ if (printSettings.isMultiline()
+ || (!matcherList.isEmpty() && invocation.length() > Whitebox.<Integer> getInternalState(
+ PrintSettings.class, "MAX_LINE_LENGTH"))) {
+ return methodName + matchersPrinter.getArgumentsBlock(matcherList, printSettings);
+ } else {
+ return invocation;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java
new file mode 100644
index 0000000..1f50ffd
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockCreator.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.creation.instance.DefaultInstantiatorProvider;
+import org.mockito.internal.handler.MockHandlerFactory;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.internal.util.reflection.LenientCopyTool;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.api.mockito.repackaged.ClassImposterizer;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+import org.powermock.core.ClassReplicaCreator;
+import org.powermock.core.DefaultFieldValueGenerator;
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class MockCreator extends AbstractMockCreator {
+
+
+ private static final MockCreator MOCK_CREATOR = new MockCreator();
+
+ @SuppressWarnings("unchecked")
+ public static <T> T mock(Class<T> type, boolean isStatic, boolean isSpy, Object delegator,
+ MockSettings mockSettings, Method... methods) {
+ return MOCK_CREATOR.createMock(type, isStatic, isSpy, delegator, mockSettings, methods);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> T createMock(Class<T> type, boolean isStatic, boolean isSpy, Object delegator,
+ MockSettings mockSettings, Method... methods) {
+ if (type == null) {
+ throw new IllegalArgumentException("The class to mock cannot be null");
+ }
+
+ validateType(type, isStatic, isSpy);
+
+ final String mockName = toInstanceName(type, mockSettings);
+
+ MockRepository.addAfterMethodRunner(new MockitoStateCleanerRunnable());
+
+ final Class<T> typeToMock;
+ if (isFinalJavaSystemClass(type)) {
+ typeToMock = (Class<T>) new ClassReplicaCreator().createClassReplica(type);
+ } else {
+ typeToMock = type;
+ }
+
+ final MockData<T> mockData = createMethodInvocationControl(mockName, typeToMock, methods, isSpy, delegator,
+ mockSettings);
+
+ T mock = mockData.getMock();
+ if (isFinalJavaSystemClass(type) && !isStatic) {
+ mock = Whitebox.newInstance(type);
+ DefaultFieldValueGenerator.fillWithDefaultValues(mock);
+ }
+
+ if (isStatic) {
+ MockRepository.putStaticMethodInvocationControl(type, mockData.getMethodInvocationControl());
+ } else {
+ MockRepository.putInstanceMethodInvocationControl(mock, mockData.getMethodInvocationControl());
+ }
+
+ if (isSpy) {
+ new LenientCopyTool().copyToMock(delegator, mock);
+ }
+
+ return mock;
+ }
+
+ private static <T> boolean isFinalJavaSystemClass(Class<T> type) {
+ return type.getName().startsWith("java.") && Modifier.isFinal(type.getModifiers());
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> MockData<T> createMethodInvocationControl(final String mockName, Class<T> type,
+ Method[] methods, boolean isSpy, Object delegator, MockSettings mockSettings) {
+ final MockSettingsImpl settings;
+ if (mockSettings == null) {
+ // We change the context classloader to the current CL in order for the Mockito
+ // framework to load it's plugins (such as MockMaker) correctly.
+ final ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(MockCreator.class.getClassLoader());
+ try {
+ settings = (MockSettingsImpl) Mockito.withSettings();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCL);
+ }
+ } else {
+ settings = (MockSettingsImpl) mockSettings;
+ }
+
+ if (isSpy) {
+ settings.defaultAnswer(Mockito.CALLS_REAL_METHODS);
+ }
+
+ settings.setMockName(new MockNameImpl(mockName));
+ settings.setTypeToMock(type);
+
+ InternalMockHandler mockHandler = new MockHandlerFactory().create(settings);
+ MethodInterceptorFilter filter = new PowerMockMethodInterceptorFilter(mockHandler, settings);
+ final T mock = new ClassImposterizer(new DefaultInstantiatorProvider().getInstantiator(settings)).imposterise(filter, type);
+ ClassLoader classLoader = mock.getClass().getClassLoader();
+ if (classLoader instanceof MockClassLoader) {
+ MockClassLoader mcl = (MockClassLoader) classLoader;
+ mcl.cache(mock.getClass());
+ }
+ final MockitoMethodInvocationControl invocationControl = new MockitoMethodInvocationControl(
+ filter,
+ isSpy && delegator == null ? new Object() : delegator,
+ mock,
+ methods);
+
+ return new MockData<T>(invocationControl, mock);
+ }
+
+ private String toInstanceName(Class<?> clazz, final MockSettings mockSettings) {
+ // if the settings define a mock name, use it
+ if (mockSettings instanceof MockSettingsImpl<?>) {
+ String settingName = ((MockSettingsImpl<?>) mockSettings).getName();
+ if (settingName != null) {
+ return settingName;
+ }
+ }
+
+ // else, use the class name as mock name
+ String className = clazz.getSimpleName();
+ if (className.length() == 0) {
+ return clazz.getName();
+ }
+ // lower case first letter
+ return className.substring(0, 1).toLowerCase() + className.substring(1);
+ }
+
+ /**
+ * Class that encapsulate a mock and its corresponding invocation control.
+ */
+ private static class MockData<T> {
+ private final MockitoMethodInvocationControl methodInvocationControl;
+
+ private final T mock;
+
+ MockData(MockitoMethodInvocationControl methodInvocationControl, T mock) {
+ this.methodInvocationControl = methodInvocationControl;
+ this.mock = mock;
+ }
+
+ public MockitoMethodInvocationControl getMethodInvocationControl() {
+ return methodInvocationControl;
+ }
+
+ public T getMock() {
+ return mock;
+ }
+ }
+
+ /**
+ * Clear state in Mockito that retains memory between tests
+ */
+ private static class MockitoStateCleanerRunnable implements Runnable {
+ public void run() {
+ MockitoStateCleaner cleaner = new MockitoStateCleaner();
+ cleaner.clearConfiguration();
+ cleaner.clearMockProgress();
+ }
+
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java
new file mode 100644
index 0000000..1a180e4
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/MockitoStateCleaner.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.internal.configuration.GlobalConfiguration;
+import org.mockito.internal.progress.ThreadSafeMockingProgress;
+import org.powermock.api.support.ClassLoaderUtil;
+import org.powermock.reflect.Whitebox;
+
+class MockitoStateCleaner {
+
+ void clearMockProgress() {
+ clearThreadLocalIn(ThreadSafeMockingProgress.class);
+ }
+
+ void clearConfiguration() {
+ clearThreadLocalIn(GlobalConfiguration.class);
+ }
+
+ private void clearThreadLocalIn(Class<?> cls) {
+ Whitebox.getInternalState(cls, ThreadLocal.class).set(null);
+ final Class<?> clazz;
+ if(ClassLoaderUtil.hasClass(cls, ClassLoader.getSystemClassLoader())) {
+ clazz = ClassLoaderUtil.loadClass(cls, ClassLoader.getSystemClassLoader());
+ } else {
+ clazz = ClassLoaderUtil.loadClass(cls, cls.getClassLoader());
+ }
+ Whitebox.getInternalState(clazz, ThreadLocal.class).set(null);
+ }
+
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java
new file mode 100644
index 0000000..397d5ee
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockcreation/PowerMockMethodInterceptorFilter.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.powermock.api.mockito.repackaged.MethodInterceptorFilter;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy;
+
+import java.lang.reflect.Method;
+
+class PowerMockMethodInterceptorFilter extends MethodInterceptorFilter {
+
+ public PowerMockMethodInterceptorFilter(InternalMockHandler handler,
+ MockCreationSettings mockSettings) {
+ super(handler, mockSettings);
+ }
+
+ @Override
+ public Object intercept(Object proxy, Method method, Object[] args,
+ MethodProxy methodProxy) throws Throwable {
+ Object intercept = super.intercept(proxy, method, args, methodProxy);
+ if ("finalize".equals(method.getName())) {
+ MockitoStateCleaner cleaner = new MockitoStateCleaner();
+ cleaner.clearConfiguration();
+ cleaner.clearMockProgress();
+ }
+ return intercept;
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java
new file mode 100644
index 0000000..52724e3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/mockmaker/PowerMockMaker.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.mockmaker;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.stubbing.InvocationContainer;
+import org.mockito.internal.util.MockNameImpl;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+import org.mockito.stubbing.Answer;
+import org.mockito.stubbing.VoidMethodStubbable;
+import org.powermock.api.mockito.repackaged.CglibMockMaker;
+import org.powermock.core.classloader.MockClassLoader;
+
+import java.util.List;
+
+/**
+ * A PowerMock implementation of the MockMaker. Right now it simply delegates to the default Mockito
+ * {@link org.mockito.plugins.MockMaker} via {@link org.mockito.internal.configuration.plugins.Plugins#getMockMaker()}
+ * but in the future we may use it more properly.
+ * The reason for its existence is that the current Mockito MockMaker throws exception when getting the name
+ * from of a mock that is created by PowerMock but not know for Mockito. This is triggered when by the
+ * {@link org.mockito.internal.util.MockUtil} class.
+ * For more details see the {@link org.powermock.api.mockito.internal.invocation.ToStringGenerator}.
+ */
+public class PowerMockMaker implements MockMaker {
+ private final MockMaker cglibMockMaker = new CglibMockMaker();
+
+ @Override
+ public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+ T mock = cglibMockMaker.createMock(settings, handler);
+ ClassLoader classLoader = cglibMockMaker.getClass().getClassLoader();
+ if (classLoader instanceof MockClassLoader) {
+ MockClassLoader mcl = (MockClassLoader) classLoader;
+ // The generated class is not picked up by PowerMock so we cache it here
+ mcl.cache(mock.getClass());
+ }
+ return mock;
+ }
+
+ @Override
+ public MockHandler getHandler(Object mock) {
+ // Return a fake mock handler for static method mocks
+ if (mock instanceof Class) {
+ return new PowerMockInternalMockHandler((Class<?>) mock);
+ } else {
+ return cglibMockMaker.getHandler(mock);
+ }
+ }
+
+ @Override
+ public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+ cglibMockMaker.resetMock(mock, newHandler, settings);
+ }
+
+ @Override
+ public TypeMockability isTypeMockable(Class<?> type) {
+ return cglibMockMaker.isTypeMockable(type);
+ }
+
+ /**
+ * It needs to extend InternalMockHandler because Mockito requires the type to be of InternalMockHandler and not MockHandler
+ */
+ private static class PowerMockInternalMockHandler implements InternalMockHandler<Object> {
+ private final Class<?> mock;
+
+ public PowerMockInternalMockHandler(Class<?> mock) {
+ this.mock = mock;
+ }
+
+ @Override
+ public MockCreationSettings getMockSettings() {
+ final MockSettingsImpl mockSettings = new MockSettingsImpl();
+ mockSettings.setMockName(new MockNameImpl(mock.getName()));
+ mockSettings.setTypeToMock(mock);
+ return mockSettings;
+ }
+
+ @Override
+ public VoidMethodStubbable<Object> voidMethodStubbable(Object mock) {
+ return null;
+ }
+
+ @Override
+ public void setAnswersForStubbing(List<Answer> answers) {
+ }
+
+ @Override
+ public InvocationContainer getInvocationContainer() {
+ return null;
+ }
+
+ @Override
+ public Object handle(Invocation invocation) throws Throwable {
+ return null;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java
new file mode 100644
index 0000000..95b777a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturns.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.internal.stubbing.answers;
+
+import org.mockito.internal.stubbing.answers.ReturnsElementsOf;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Created by gauee on 12/11/15.
+ */
+public class ChainReturns implements Answer<Object> {
+ private final ReturnsElementsOf returnsElementsOf;
+
+ public ChainReturns(Object toBeReturn, Object... toBeReturnedOthers) {
+ List<Object> elements = new LinkedList<Object>();
+ elements.add(toBeReturn);
+ addOtherElementToBeReturned(elements, toBeReturnedOthers);
+
+ this.returnsElementsOf = new ReturnsElementsOf(elements);
+
+ }
+
+ private void addOtherElementToBeReturned(List<Object> elements, Object[] toBeReturnedOthers) {
+ if (toBeReturnedOthers == null) {
+ elements.add(toBeReturnedOthers);
+ return;
+ }
+ for (Object toBeReturnedOther : toBeReturnedOthers) {
+ elements.add(toBeReturnedOther);
+ }
+ }
+
+ @Override
+ public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
+ return returnsElementsOf.answer(invocationOnMock);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java
new file mode 100644
index 0000000..07f690a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultConstructorArgumentsVerfication.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.powermock.api.mockito.internal.invocation.InvocationControlAssertionError;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.api.mockito.verification.ConstructorArgumentsVerification;
+import org.powermock.core.spi.NewInvocationControl;
+
+public class DefaultConstructorArgumentsVerfication<T> implements ConstructorArgumentsVerification {
+
+ private final MockitoNewInvocationControl<T> invocationControl;
+ private final Class<?> type;
+
+ @SuppressWarnings("unchecked")
+ public DefaultConstructorArgumentsVerfication(NewInvocationControl<T> invocationControl, Class<?> type) {
+ this.type = type;
+ this.invocationControl = (MockitoNewInvocationControl<T>) invocationControl;
+ }
+
+ @Override
+ public void withArguments(Object argument, Object... arguments) throws Exception {
+ final Object[] realArguments;
+ if (arguments == null) {
+ realArguments = new Object[]{argument, null};
+ } else {
+ realArguments = new Object[arguments.length + 1];
+ realArguments[0] = argument;
+ System.arraycopy(arguments, 0, realArguments, 1, arguments.length);
+ }
+ invokeSubstitute(realArguments);
+ }
+
+ private void invokeSubstitute(Object... arguments) throws Exception {
+ try {
+ invocationControl.getSubstitute().performSubstitutionLogic(arguments);
+ } catch (MockitoAssertionError e) {
+ InvocationControlAssertionError.throwAssertionErrorForNewSubstitutionFailure(e, type);
+ }
+ }
+
+ @Override
+ public void withNoArguments() throws Exception {
+ invokeSubstitute(new Object[0]);
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java
new file mode 100644
index 0000000..bc934d9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/DefaultPrivateMethodVerification.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.powermock.api.mockito.verification.PrivateMethodVerification;
+import org.powermock.api.mockito.verification.WithOrWithoutVerifiedArguments;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.impl.ArrayMergerImpl;
+
+import java.lang.reflect.Method;
+
+public class DefaultPrivateMethodVerification implements PrivateMethodVerification {
+
+ private final Object objectToVerify;
+
+ public DefaultPrivateMethodVerification(Object objectToVerify) {
+ this.objectToVerify = objectToVerify;
+ }
+
+ @Override
+ public void invoke(Object... arguments) throws Exception {
+ Whitebox.invokeMethod(objectToVerify, arguments);
+
+ }
+
+ @Override
+ public void invoke(String methodToExecute, Object... arguments) throws Exception {
+ Whitebox.invokeMethod(objectToVerify, methodToExecute, (Object[]) arguments);
+ }
+
+ @Override
+ public WithOrWithoutVerifiedArguments invoke(Method method) throws Exception {
+ return new VerificationArguments(method);
+ }
+
+ private class VerificationArguments implements WithOrWithoutVerifiedArguments {
+ private final Method method;
+
+ public VerificationArguments(Method method) {
+ if (method == null) {
+ throw new IllegalArgumentException("method cannot be null");
+ }
+ this.method = method;
+ this.method.setAccessible(true);
+ }
+
+ @Override
+ public void withArguments(Object firstArgument, Object... additionalArguments) throws Exception {
+ if (additionalArguments == null || additionalArguments.length == 0) {
+ method.invoke(objectToVerify, firstArgument);
+ } else {
+ Object[] arguments = new ArrayMergerImpl().mergeArrays(Object.class, new Object[]{firstArgument}, additionalArguments);
+ method.invoke(objectToVerify, arguments);
+ }
+ }
+
+ @Override
+ public void withNoArguments() throws Exception {
+ method.invoke(objectToVerify);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java
new file mode 100644
index 0000000..57a608d
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/StaticMockAwareVerificationMode.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.internal.verification.MockAwareVerificationMode;
+import org.mockito.internal.verification.api.VerificationData;
+import org.mockito.invocation.MockHandler;
+import org.mockito.verification.VerificationMode;
+
+/**
+ * A custom extension of {@link MockAwareVerificationMode} for static method
+ * verification. The reason for this implementation is that since Mockito 1.8.4
+ * the verification code in Mockito
+ * {@link MockHandler#handle(org.mockito.internal.invocation.Invocation)} has
+ * changed and the verification mode MUST be an instance of
+ * {@link MockAwareVerificationMode} for the verification to work. Since
+ * verifying static methods is a two step process in PowerMock we need to be
+ * able to specify the class a later state then verification start. I.e. in
+ * standard Mockito they always know the mock object when doing verify before
+ * calling the method to verify:
+ *
+ * <pre>
+ * verify(mock).methodToVerify();
+ * </pre>
+ *
+ * In PowerMock we don't know the class when calling verifyStatic().
+ */
+public class StaticMockAwareVerificationMode extends MockAwareVerificationMode {
+
+ private Class<?> clsMock;
+
+ public StaticMockAwareVerificationMode(VerificationMode mode) {
+ super(null, mode);
+ }
+
+ public void setClassMock(Class<?> clsMock) {
+ this.clsMock = clsMock;
+ }
+
+ @Override
+ public void verify(VerificationData data) {
+ super.verify(data);
+ }
+
+ @Override
+ public Object getMock() {
+ return clsMock;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java
new file mode 100644
index 0000000..01ea80f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/internal/verification/VerifyNoMoreInteractions.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.internal.verification;
+
+import org.mockito.Mockito;
+import org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl;
+import org.powermock.api.mockito.internal.invocation.MockitoNewInvocationControl;
+import org.powermock.core.MockRepository;
+
+/**
+ * Verifies no more interactions, delegates to Mockito if PowerMockito doesn't
+ * find a supplied mock.
+ */
+public class VerifyNoMoreInteractions {
+
+ public static void verifyNoMoreInteractions(Object... objects) {
+ for (Object mock : objects) {
+ if (mock instanceof Class<?>) {
+ verifyNoMoreInteractions((Class<?>) mock);
+ } else {
+ MockitoMethodInvocationControl invocationControl = (MockitoMethodInvocationControl) MockRepository
+ .getInstanceMethodInvocationControl(mock);
+ if (invocationControl != null) {
+ invocationControl.verifyNoMoreInteractions();
+ } else {
+ /*
+ * Delegate to Mockito if we have no handler registered for
+ * this object.
+ */
+ Mockito.verifyNoMoreInteractions(mock);
+ }
+ }
+ }
+ }
+
+ private static void verifyNoMoreInteractions(Class<?>... types) {
+ for (Class<?> type : types) {
+ final MockitoMethodInvocationControl invocationHandler = (MockitoMethodInvocationControl) MockRepository
+ .getStaticMethodInvocationControl(type);
+ if (invocationHandler != null) {
+ invocationHandler.verifyNoMoreInteractions();
+ }
+ MockitoNewInvocationControl<?> newInvocationControl = (MockitoNewInvocationControl<?>) MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ newInvocationControl.verifyNoMoreInteractions();
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java
new file mode 100644
index 0000000..e4d5d1f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/mockpolicies/Slf4jMockPolicy.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.mockito.mockpolicies;
+
+import org.mockito.Mockito;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.mockpolicies.support.LogPolicySupport;
+
+import java.lang.reflect.Method;
+
+/**
+ * Sfl4j mock policy that injects a Mockito-created mock to be returned on calls to getLogger factory methods.
+ * The implementation returns a single mock instance per thread but it doesn't return a different mock instance based
+ * on the actual value passed to getLogger. This limitation is acceptable in most real uses cases.
+ * <p/>
+ * Tests that want to do verifications on the mocked logger can do so by getting the mocked instance as production code
+ * does: {@link org.slf4j.LoggerFactory#getLogger(Class)}. However, it is critical that the mocked logger is
+ * reset after each test in order to avoid crosstalk between test cases.
+ * <p/>
+ *
+ * @author Alexandre Normand <alexandre.normand at gmail.com>
+ */
+public class Slf4jMockPolicy implements PowerMockPolicy {
+
+ private static final String LOGGER_FACTORY_CLASS_NAME = "org.slf4j.LoggerFactory";
+ private static final String LOGGER_FACTORY_METHOD_NAME = "getLogger";
+ private static final String FRAMEWORK_NAME = "sfl4j";
+ private static final String LOGGER_CLASS_NAME = "org.slf4j.Logger";
+
+ private static ThreadLocal<Object> threadLogger = new ThreadLocal<Object>();
+
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings mockPolicyClassLoadingSettings) {
+ mockPolicyClassLoadingSettings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(
+ LOGGER_FACTORY_CLASS_NAME,
+ "org.apache.log4j.Appender",
+ "org.apache.log4j.xml.DOMConfigurator");
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings mockPolicyInterceptionSettings) {
+ LogPolicySupport logPolicySupport = new LogPolicySupport();
+
+ Method[] loggerFactoryMethods = logPolicySupport.getLoggerMethods(LOGGER_FACTORY_CLASS_NAME,
+ LOGGER_FACTORY_METHOD_NAME, FRAMEWORK_NAME);
+
+ initializeMockForThread(logPolicySupport);
+
+ for (Method loggerFactoryMethod : loggerFactoryMethods) {
+ mockPolicyInterceptionSettings.stubMethod(loggerFactoryMethod, threadLogger.get());
+ }
+ }
+
+ private void initializeMockForThread(LogPolicySupport logPolicySupport) {
+ Class<?> loggerClass = getLoggerClass(logPolicySupport);
+
+ if (threadLogger.get() == null) {
+ /*
+ * When mocking with Mockito we need to change the context CL to the same CL that is loading Mockito
+ * otherwise the Mockito plugin mechanism will load the PowerMockMaker from the wrong classloader.
+ */
+ final ClassLoader originalCl = Thread.currentThread().getContextClassLoader();
+ final ClassLoader classLoader = Mockito.class.getClassLoader();
+ Thread.currentThread().setContextClassLoader(classLoader);
+ final Object mock;
+ try {
+ mock = Mockito.mock(loggerClass);
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCl);
+ }
+
+ threadLogger.set(mock);
+ }
+ }
+
+ private Class<?> getLoggerClass(LogPolicySupport logPolicySupport) {
+ Class<?> loggerType;
+ try {
+ loggerType = logPolicySupport.getType(LOGGER_CLASS_NAME, FRAMEWORK_NAME);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ return loggerType;
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java b/api/mockito2/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java
new file mode 100644
index 0000000..adb9c47
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/powermocklistener/AnnotationEnabler.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.powermocklistener;
+
+/**
+ * Before each test method all fields annotated with {@link Mock},
+ * {@link org.mockito.Mock} or {@link Mock} have mock objects created for them
+ * and injected to the fields.
+ *
+ * @deprecated Test Runners uses an annotation enabling listener per default
+ * since version 1.3. You should just remove this listener.
+ */
+public class AnnotationEnabler extends org.powermock.api.extension.listener.AnnotationEnabler {
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java
new file mode 100644
index 0000000..3ed2690
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/AcrossJVMSerializationFeature.java
@@ -0,0 +1,429 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.Incubating;
+import org.mockito.exceptions.base.MockitoSerializationIssue;
+import org.mockito.internal.creation.instance.DefaultInstantiatorProvider;
+import org.mockito.internal.creation.settings.CreationSettings;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.internal.util.reflection.FieldSetter;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.mock.MockName;
+import org.mockito.mock.SerializableMode;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InvalidObjectException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.ObjectStreamException;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+import static org.mockito.internal.util.StringJoiner.join;
+
+/**
+ * This is responsible for serializing a mock, it is enabled if the mock is implementing
+ * {@link Serializable}.
+ * <p/>
+ * <p>
+ * The way it works is to enable serialization via the {@link #enableSerializationAcrossJVM(MockCreationSettings)},
+ * if the mock settings is set to be serializable it will add the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable}
+ * interface.
+ * This interface defines a the {@link AcrossJVMSerializationFeature.AcrossJVMMockitoMockSerializable#writeReplace()}
+ * whose signature match the one that is looked by the standard Java serialization.
+ * </p>
+ * <p/>
+ * <p>
+ * Then in the {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter} of mockito, if the <code>writeReplace</code> method is called,
+ * it will use the custom implementation of this class {@link #writeReplace(Object)}. This method has a specific
+ * knowledge on how to serialize a mockito mock that is based on CGLIB.
+ * </p>
+ *
+ * <p><strong>Only one instance per mock! See {@link org.mockito.internal.creation.cglib.MethodInterceptorFilter}</strong></p>
+ *
+ * TODO use a proper way to add the interface
+ * TODO offer a way to disable completely this behavior, or maybe enable this behavior only with a specific setting
+ * TODO check the class is mockable in the deserialization side
+ *
+ * @see org.mockito.internal.creation.cglib.CglibMockMaker
+ * @see org.mockito.internal.creation.cglib.MethodInterceptorFilter
+ * @author Brice Dutheil
+ * @since 1.10.0
+ */
+ at Incubating
+class AcrossJVMSerializationFeature implements Serializable {
+ private static final long serialVersionUID = 7411152578314420778L;
+ private static final String MOCKITO_PROXY_MARKER = "MockitoProxyMarker";
+ private final Lock mutex = new ReentrantLock();
+ private boolean instanceLocalCurrentlySerializingFlag = false;
+
+ public boolean isWriteReplace(Method method) {
+ return method.getReturnType() == Object.class
+ && method.getParameterTypes().length == 0
+ && method.getName().equals("writeReplace");
+ }
+
+
+ /**
+ * Custom implementation of the <code>writeReplace</code> method for serialization.
+ * <p/>
+ * Here's how it's working and why :
+ * <ol>
+ * <li>
+ * <p>When first entering in this method, it's because some is serializing the mock, with some code like :
+ * <pre class="code"><code class="java">
+ * objectOutputStream.writeObject(mock);
+ * </code></pre>
+ * So, {@link ObjectOutputStream} will track the <code>writeReplace</code> method in the instance and
+ * execute it, which is wanted to replace the mock by another type that will encapsulate the actual mock.
+ * At this point, the code will return an
+ * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy}.</p>
+ * </li>
+ * <li>
+ * <p>Now, in the constructor
+ * {@link AcrossJVMSerializationFeature.AcrossJVMMockSerializationProxy#AcrossJVMMockSerializationProxy(Object)}
+ * the mock is being serialized in a custom way (using
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream}) to a
+ * byte array. So basically it means the code is performing double nested serialization of the passed
+ * <code>mockitoMock</code>.</p>
+ *
+ * <p>However the <code>ObjectOutputStream</code> will still detect the custom
+ * <code>writeReplace</code> and execute it.
+ * <em>(For that matter disabling replacement via {@link ObjectOutputStream#enableReplaceObject(boolean)}
+ * doesn't disable the <code>writeReplace</code> call, but just just toggle replacement in the
+ * written stream, <strong><code>writeReplace</code> is always called by
+ * <code>ObjectOutputStream</code></strong>.)</em></p>
+ *
+ * <p>In order to avoid this recursion, obviously leading to a {@link StackOverflowError}, this method is using
+ * a flag that marks the mock as already being replaced, and then shouldn't replace itself again.
+ * <strong>This flag is local to this class</strong>, which means the flag of this class unfortunately needs
+ * to be protected against concurrent access, hence the reentrant lock.</p>
+ * </li>
+ * </ol>
+ *
+ * @param mockitoMock The Mockito mock to be serialized.
+ * @return A wrapper ({@link AcrossJVMMockSerializationProxy}) to be serialized by the calling ObjectOutputStream.
+ * @throws ObjectStreamException
+ */
+ public Object writeReplace(Object mockitoMock) throws ObjectStreamException {
+ try {
+ // reentrant lock for critical section. could it be improved ?
+ mutex.lock();
+ // mark started flag // per thread, not per instance
+ // temporary loosy hack to avoid stackoverflow
+ if (mockIsCurrentlyBeingReplaced()) {
+ return mockitoMock;
+ }
+ mockReplacementStarted();
+
+ return new AcrossJVMMockSerializationProxy(mockitoMock);
+ } catch (IOException ioe) {
+ MockUtil mockUtil = new MockUtil();
+ MockName mockName = mockUtil.getMockName(mockitoMock);
+ String mockedType = mockUtil.getMockSettings(mockitoMock).getTypeToMock().getCanonicalName();
+ throw new MockitoSerializationIssue(join(
+ "The mock '" + mockName + "' of type '" + mockedType + "'",
+ "The Java Standard Serialization reported an '" + ioe.getClass().getSimpleName() + "' saying :",
+ " " + ioe.getMessage()
+ ), ioe);
+ } finally {
+ // unmark
+ mockReplacementCompleted();
+ mutex.unlock();
+ }
+ }
+
+
+ private void mockReplacementCompleted() {
+ instanceLocalCurrentlySerializingFlag = false;
+ }
+
+
+ private void mockReplacementStarted() {
+ instanceLocalCurrentlySerializingFlag = true;
+ }
+
+
+ private boolean mockIsCurrentlyBeingReplaced() {
+ return instanceLocalCurrentlySerializingFlag;
+ }
+
+
+ /**
+ * Enable serialization serialization that will work across classloaders / and JVM.
+ * <p/>
+ * <p>Only enable if settings says the mock should be serializable. In this case add the
+ * {@link AcrossJVMMockitoMockSerializable} to the extra interface list.</p>
+ *
+ * @param settings Mock creation settings.
+ * @param <T> Type param to not be bothered by the generics
+ */
+ public <T> void enableSerializationAcrossJVM(MockCreationSettings<T> settings) {
+ if (settings.getSerializableMode() == SerializableMode.ACROSS_CLASSLOADERS) {
+ // havin faith that this set is modifiable
+ // TODO use a proper way to add the interface
+ settings.getExtraInterfaces().add(AcrossJVMMockitoMockSerializable.class);
+ }
+ }
+
+
+ /**
+ * Simple interface that hold a correct <code>writeReplace</code> signature that can be seen by an
+ * <code>ObjectOutputStream</code>.
+ * <p/>
+ * It will be applied before the creation of the mock when the mock setting says it should serializable.
+ *
+ * @see #enableSerializationAcrossJVM(org.mockito.mock.MockCreationSettings)
+ */
+ public interface AcrossJVMMockitoMockSerializable {
+ public Object writeReplace() throws ObjectStreamException;
+ }
+
+ /**
+ * This is the serialization proxy that will encapsulate the real mock data as a byte array.
+ * <p/>
+ * <p>When called in the constructor it will serialize the mock in a byte array using a
+ * custom {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream} that
+ * will annotate the mock class in the stream.
+ * Other information are used in this class in order to facilitate deserialization.
+ * </p>
+ * <p/>
+ * <p>Deserialization of the mock will be performed by the {@link #readResolve()} method via
+ * the custom {@link MockitoMockObjectInputStream} that will be in charge of creating the mock class.</p>
+ */
+ public static class AcrossJVMMockSerializationProxy implements Serializable {
+
+
+ private static final long serialVersionUID = -7600267929109286514L;
+ private final byte[] serializedMock;
+ private final Class typeToMock;
+ private final Set<Class> extraInterfaces;
+
+ /**
+ * Creates the wrapper that be used in the serialization stream.
+ *
+ * <p>Immediately serializes the Mockito mock using specifically crafted
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream},
+ * in a byte array.</p>
+ *
+ * @param mockitoMock The Mockito mock to serialize.
+ * @throws IOException
+ */
+ public AcrossJVMMockSerializationProxy(Object mockitoMock) throws IOException {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ ObjectOutputStream objectOutputStream = new MockitoMockObjectOutputStream(out);
+
+ objectOutputStream.writeObject(mockitoMock);
+
+ objectOutputStream.close();
+ out.close();
+
+ MockCreationSettings mockSettings = new MockUtil().getMockSettings(mockitoMock);
+ this.serializedMock = out.toByteArray();
+ this.typeToMock = mockSettings.getTypeToMock();
+ this.extraInterfaces = mockSettings.getExtraInterfaces();
+ }
+
+ /**
+ * Resolves the proxy to a new deserialized instance of the Mockito mock.
+ * <p/>
+ * <p>Uses the custom crafted {@link MockitoMockObjectInputStream} to deserialize the mock.</p>
+ *
+ * @return A deserialized instance of the Mockito mock.
+ * @throws ObjectStreamException
+ */
+ private Object readResolve() throws ObjectStreamException {
+ try {
+ ByteArrayInputStream bis = new ByteArrayInputStream(serializedMock);
+ ObjectInputStream objectInputStream = new MockitoMockObjectInputStream(bis, typeToMock, extraInterfaces);
+
+ Object deserializedMock = objectInputStream.readObject();
+
+ bis.close();
+ objectInputStream.close();
+
+ return deserializedMock;
+ } catch (IOException ioe) {
+ throw new MockitoSerializationIssue(join(
+ "Mockito mock cannot be deserialized to a mock of '" + typeToMock.getCanonicalName() + "'. The error was :",
+ " " + ioe.getMessage(),
+ "If you are unsure what is the reason of this exception, feel free to contact us on the mailing list."
+ ), ioe);
+ } catch (ClassNotFoundException cce) {
+ throw new MockitoSerializationIssue(join(
+ "A class couldn't be found while deserializing a Mockito mock, you should check your classpath. The error was :",
+ " " + cce.getMessage(),
+ "If you are still unsure what is the reason of this exception, feel free to contact us on the mailing list."
+ ), cce);
+ }
+ }
+ }
+
+ /**
+ * Special Mockito aware <code>ObjectInputStream</code> that will resolve the Mockito proxy class.
+ * <p/>
+ * <p>
+ * This specificaly crafted ObjectInoutStream has the most important role to resolve the Mockito generated
+ * class. It is doing so via the {@link #resolveClass(ObjectStreamClass)} which looks in the stream
+ * for a Mockito marker. If this marker is found it will try to resolve the mockito class otherwise it
+ * delegates class resolution to the default super behavior.
+ * The mirror method used for serializing the mock is
+ * {@link AcrossJVMSerializationFeature.MockitoMockObjectOutputStream#annotateClass(Class)}.
+ * </p>
+ * <p/>
+ * <p>
+ * When this marker is found, {@link org.mockito.internal.creation.cglib.ClassImposterizer} methods are being used to create the mock class.
+ * <em>Note that behind the <code>ClassImposterizer</code> there is CGLIB and the
+ * {@link org.mockito.internal.creation.util.SearchingClassLoader} that will look if this enhanced class has
+ * already been created in an accessible classloader ; so basically this code trusts the ClassImposterizer
+ * code.</em>
+ * </p>
+ */
+ public static class MockitoMockObjectInputStream extends ObjectInputStream {
+ private final Class typeToMock;
+ private final Set<Class> extraInterfaces;
+
+ public MockitoMockObjectInputStream(InputStream in, Class typeToMock, Set<Class> extraInterfaces) throws IOException {
+ super(in);
+ this.typeToMock = typeToMock;
+ this.extraInterfaces = extraInterfaces;
+ enableResolveObject(true); // ensure resolving is enabled
+ }
+
+ /**
+ * Resolve the Mockito proxy class if it is marked as such.
+ * <p/>
+ * <p>Uses the fields {@link #typeToMock} and {@link #extraInterfaces} to
+ * create the Mockito proxy class as the <code>ObjectStreamClass</code>
+ * doesn't carry useful information for this purpose.</p>
+ *
+ * @param desc Description of the class in the stream, not used.
+ * @return The class that will be used to deserialize the instance mock.
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
+ if (notMarkedAsAMockitoMock(readObject())) {
+ return super.resolveClass(desc);
+ }
+
+ // TODO check the class is mockable in the deserialization side
+ // ClassImposterizer.INSTANCE.canImposterise(typeToMock);
+
+ // create the Mockito mock class before it can even be deserialized
+ //TODO SF unify creation of imposterizer, constructor code duplicated
+ ClassImposterizer imposterizer = new ClassImposterizer(new DefaultInstantiatorProvider().getInstantiator(new CreationSettings()));
+ imposterizer.setConstructorsAccessible(typeToMock, true);
+ Class<?> proxyClass = imposterizer.createProxyClass(
+ typeToMock,
+ extraInterfaces.toArray(new Class[extraInterfaces.size()])
+ );
+
+ hackClassNameToMatchNewlyCreatedClass(desc, proxyClass);
+ return proxyClass;
+ }
+
+ /**
+ * Hack the <code>name</code> field of the given <code>ObjectStreamClass</code> with
+ * the <code>newProxyClass</code>.
+ * <p/>
+ * The parent ObjectInputStream will check the name of the class in the stream matches the name of the one
+ * that is created in this method.
+ * <p/>
+ * The CGLIB classes uses a hash of the classloader and/or maybe some other data that allow them to be
+ * relatively unique in a JVM.
+ * <p/>
+ * When names differ, which happens when the mock is deserialized in another ClassLoader, a
+ * <code>java.io.InvalidObjectException</code> is thrown, so this part of the code is hacking through
+ * the given <code>ObjectStreamClass</code> to change the name with the newly created class.
+ *
+ * @param descInstance The <code>ObjectStreamClass</code> that will be hacked.
+ * @param proxyClass The proxy class whose name will be applied.
+ * @throws InvalidObjectException
+ */
+ private void hackClassNameToMatchNewlyCreatedClass(ObjectStreamClass descInstance, Class<?> proxyClass) throws ObjectStreamException {
+ try {
+ Field classNameField = descInstance.getClass().getDeclaredField("name");
+ new FieldSetter(descInstance, classNameField).set(proxyClass.getCanonicalName());
+ } catch (NoSuchFieldException nsfe) {
+ // TODO use our own mockito mock serialization exception
+ throw new MockitoSerializationIssue(join(
+ "Wow, the class 'ObjectStreamClass' in the JDK don't have the field 'name',",
+ "this is definitely a bug in our code as it means the JDK team changed a few internal things.",
+ "",
+ "Please report an issue with the JDK used, a code sample and a link to download the JDK would be welcome."
+ ), nsfe);
+ }
+ }
+
+ /**
+ * Read the stream class annotation and identify it as a Mockito mock or not.
+ *
+ * @param marker The marker to identify.
+ * @return <code>true</code> if not marked as a Mockito, <code>false</code> if the class annotation marks a Mockito mock.
+ * @throws IOException
+ * @throws ClassNotFoundException
+ */
+ private boolean notMarkedAsAMockitoMock(Object marker) throws IOException, ClassNotFoundException {
+ return !MOCKITO_PROXY_MARKER.equals(marker);
+ }
+ }
+
+ /**
+ * Special Mockito aware <code>ObjectOutputStream</code>.
+ * <p/>
+ * <p>
+ * This output stream has the role of marking in the stream the Mockito class. This
+ * marking process is necessary to identify the proxy class that will need to be recreated.
+ * <p/>
+ * The mirror method used for deserializing the mock is
+ * {@link MockitoMockObjectInputStream#resolveClass(ObjectStreamClass)}.
+ * </p>
+ */
+ private static class MockitoMockObjectOutputStream extends ObjectOutputStream {
+ private static final String NOTHING = "";
+
+ public MockitoMockObjectOutputStream(ByteArrayOutputStream out) throws IOException {
+ super(out);
+ }
+
+ /**
+ * Annotates (marks) the class if this class is a Mockito mock.
+ *
+ * @param cl The class to annotate.
+ * @throws IOException
+ */
+ @Override
+ protected void annotateClass(Class<?> cl) throws IOException {
+ writeObject(mockitoProxyClassMarker(cl));
+ // might be also useful later, for embedding classloader info ...maybe ...maybe not
+ }
+
+ /**
+ * Returns the Mockito marker if this class is a Mockito mock.
+ *
+ * @param cl The class to mark.
+ * @return The marker if this is a Mockito proxy class, otherwise returns a void marker.
+ */
+ private String mockitoProxyClassMarker(Class<?> cl) {
+ if (AcrossJVMMockitoMockSerializable.class.isAssignableFrom(cl)) {
+ return MOCKITO_PROXY_MARKER;
+ } else {
+ return NOTHING;
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java
new file mode 100644
index 0000000..a78a962
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CGLIBHacker.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy;
+
+import java.lang.reflect.Field;
+
+class CGLIBHacker {
+
+ public void setMockitoNamingPolicy(MethodProxy methodProxy) {
+ try {
+ Field createInfoField = reflectOnCreateInfo(methodProxy);
+ createInfoField.setAccessible(true);
+ Object createInfo = createInfoField.get(methodProxy);
+ Field namingPolicyField = createInfo.getClass().getDeclaredField("namingPolicy");
+ namingPolicyField.setAccessible(true);
+ if (namingPolicyField.get(createInfo) == null) {
+ namingPolicyField.set(createInfo, MockitoNamingPolicy.INSTANCE);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(
+ "Unable to set MockitoNamingPolicy on cglib generator which creates FastClasses", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private Field reflectOnCreateInfo(MethodProxy methodProxy) throws SecurityException, NoSuchFieldException {
+
+ Class cglibMethodProxyClass = methodProxy.getClass();
+ // in case methodProxy was extended by user, let's traverse the object
+ // graph to find the cglib methodProxy
+ // with all the fields we would like to change
+ while (cglibMethodProxyClass != MethodProxy.class) {
+ cglibMethodProxyClass = methodProxy.getClass().getSuperclass();
+ }
+ return cglibMethodProxyClass.getDeclaredField("createInfo");
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java
new file mode 100644
index 0000000..0fa62c3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/CglibMockMaker.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.instance.DefaultInstantiatorProvider;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.mockito.plugins.MockMaker;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Callback;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Factory;
+
+import java.lang.reflect.Modifier;
+
+
+/**
+ * A MockMaker that uses cglib to generate mocks on a JVM.
+ */
+public class CglibMockMaker implements MockMaker {
+
+ public <T> T createMock(MockCreationSettings<T> settings, MockHandler handler) {
+ InternalMockHandler mockitoHandler = cast(handler);
+ new AcrossJVMSerializationFeature().enableSerializationAcrossJVM(settings);
+ return new ClassImposterizer(new DefaultInstantiatorProvider().getInstantiator(settings)).imposterise(
+ new MethodInterceptorFilter(mockitoHandler, settings), settings.getTypeToMock(), settings.getExtraInterfaces());
+ }
+
+ private InternalMockHandler cast(MockHandler handler) {
+ if (!(handler instanceof InternalMockHandler)) {
+ throw new MockitoException("At the moment you cannot provide own implementations of MockHandler." +
+ "\nPlease see the javadocs for the MockMaker interface.");
+ }
+ return (InternalMockHandler) handler;
+ }
+
+ public void resetMock(Object mock, MockHandler newHandler, MockCreationSettings settings) {
+ ((Factory) mock).setCallback(0, new MethodInterceptorFilter(cast(newHandler), settings));
+ }
+
+ public MockHandler getHandler(Object mock) {
+ if (!(mock instanceof Factory)) {
+ return null;
+ }
+ Factory factory = (Factory) mock;
+ Callback callback = factory.getCallback(0);
+ if (!(callback instanceof MethodInterceptorFilter)) {
+ return null;
+ }
+ return ((MethodInterceptorFilter) callback).getHandler();
+ }
+
+ public TypeMockability isTypeMockable(final Class<?> type) {
+ return new TypeMockability() {
+ public boolean mockable() {
+ return !type.isPrimitive() && !Modifier.isFinal(type.getModifiers());
+ }
+
+ public String nonMockableReason() {
+ if(type.isPrimitive()) {
+ return "primitive type";
+ }
+ if(Modifier.isFinal(type.getModifiers())) {
+ return "final or anonymous class";
+ }
+ return "";
+ }
+ };
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java
new file mode 100644
index 0000000..3bade42
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/ClassImposterizer.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.exceptions.base.MockitoException;
+import org.mockito.internal.creation.instance.InstantiationException;
+import org.mockito.internal.creation.instance.Instantiator;
+import org.mockito.internal.creation.util.SearchingClassLoader;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.NamingPolicy;
+import org.powermock.api.mockito.repackaged.cglib.core.Predicate;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Callback;
+import org.powermock.api.mockito.repackaged.cglib.proxy.CallbackFilter;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Enhancer;
+import org.powermock.api.mockito.repackaged.cglib.proxy.Factory;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodInterceptor;
+import org.powermock.api.mockito.repackaged.cglib.proxy.NoOp;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Collection;
+import java.util.List;
+
+import static org.mockito.internal.util.StringJoiner.join;
+
+/**
+ * Inspired on jMock (thanks jMock guys!!!)
+ */
+public class ClassImposterizer {
+
+ private static final NamingPolicy NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES = new MockitoNamingPolicy() {
+ @Override
+ public String getClassName(String prefix, String source, Object key, Predicate names) {
+ return "codegen." + super.getClassName(prefix, source, key, names);
+ }
+ };
+ private static final CallbackFilter IGNORE_BRIDGE_METHODS = new CallbackFilter() {
+ public int accept(Method method, List<Method> allMethods) {
+ return method.isBridge() ? 1 : 0;
+ }
+ };
+ private final Instantiator instantiator;
+
+ public ClassImposterizer(Instantiator instantiator) {
+ this.instantiator = instantiator;
+ }
+
+ private static String describeClass(Class type) {
+ return type == null? "null" : "'" + type.getCanonicalName() + "', loaded by classloader : '" + type.getClassLoader() + "'";
+ }
+
+ private static String describeClass(Object instance) {
+ return instance == null? "null" : describeClass(instance.getClass());
+ }
+
+ @SuppressWarnings("unchecked")
+ public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Collection<Class<?>> ancillaryTypes) {
+ return (T) imposterise(interceptor, mockedType, ancillaryTypes.toArray(new Class[ancillaryTypes.size()]));
+ }
+
+ public <T> T imposterise(final MethodInterceptor interceptor, Class<T> mockedType, Class<?>... ancillaryTypes) {
+ Class<Factory> proxyClass = null;
+ Object proxyInstance = null;
+ try {
+ setConstructorsAccessible(mockedType, true);
+ proxyClass = createProxyClass(mockedType, ancillaryTypes);
+ proxyInstance = createProxy(proxyClass, interceptor);
+ return mockedType.cast(proxyInstance);
+ } catch (ClassCastException cce) {
+ throw new MockitoException(join(
+ "ClassCastException occurred while creating the mockito proxy :",
+ " class to mock : " + describeClass(mockedType),
+ " created class : " + describeClass(proxyClass),
+ " proxy instance class : " + describeClass(proxyInstance),
+ " instance creation by : " + instantiator.getClass().getSimpleName(),
+ "",
+ "You might experience classloading issues, disabling the Objenesis cache *might* help (see MockitoConfiguration)"
+ ), cce);
+ } finally {
+ setConstructorsAccessible(mockedType, false);
+ }
+ }
+
+ //TODO this method does not belong here
+ public void setConstructorsAccessible(Class<?> mockedType, boolean accessible) {
+ for (Constructor<?> constructor : mockedType.getDeclaredConstructors()) {
+ constructor.setAccessible(accessible);
+ }
+ }
+
+ public Class<Factory> createProxyClass(Class<?> mockedType, Class<?>... interfaces) {
+ if (mockedType == Object.class) {
+ mockedType = ClassWithSuperclassToWorkAroundCglibBug.class;
+ }
+
+ Enhancer enhancer = new Enhancer() {
+ @Override
+ @SuppressWarnings("unchecked")
+ protected void filterConstructors(Class sc, List constructors) {
+ // Don't filter
+ }
+ };
+ Class<?>[] allMockedTypes = prepend(mockedType, interfaces);
+ enhancer.setClassLoader(SearchingClassLoader.combineLoadersOf(allMockedTypes));
+ enhancer.setUseFactory(true);
+ if (mockedType.isInterface()) {
+ enhancer.setSuperclass(Object.class);
+ enhancer.setInterfaces(allMockedTypes);
+ } else {
+ enhancer.setSuperclass(mockedType);
+ enhancer.setInterfaces(interfaces);
+ }
+ enhancer.setCallbackTypes(new Class[]{MethodInterceptor.class, NoOp.class});
+ enhancer.setCallbackFilter(IGNORE_BRIDGE_METHODS);
+ if (mockedType.getSigners() != null) {
+ enhancer.setNamingPolicy(NAMING_POLICY_THAT_ALLOWS_IMPOSTERISATION_OF_CLASSES_IN_SIGNED_PACKAGES);
+ } else {
+ enhancer.setNamingPolicy(MockitoNamingPolicy.INSTANCE);
+ }
+
+ enhancer.setSerialVersionUID(42L);
+
+ try {
+ return enhancer.createClass();
+ } catch (CodeGenerationException e) {
+ if (Modifier.isPrivate(mockedType.getModifiers())) {
+ throw new MockitoException("\n"
+ + "Mockito cannot mock this class: " + mockedType
+ + ".\n"
+ + "Most likely it is a private class that is not visible by Mockito");
+ }
+ throw new MockitoException("\n"
+ + "Mockito cannot mock this class: " + mockedType
+ + "\n"
+ + "Mockito can only mock visible & non-final classes."
+ + "\n"
+ + "If you're not sure why you're getting this error, please report to the mailing list.", e);
+ }
+ }
+
+ private Object createProxy(Class<Factory> proxyClass, final MethodInterceptor interceptor) {
+ Factory proxy;
+ try {
+ proxy = instantiator.newInstance(proxyClass);
+ } catch (InstantiationException e) {
+ throw new MockitoException("Unable to create mock instance of type '" + proxyClass.getSuperclass().getSimpleName() + "'", e);
+ }
+ proxy.setCallbacks(new Callback[] {interceptor, SerializableNoOp.SERIALIZABLE_INSTANCE });
+ return proxy;
+ }
+
+ private Class<?>[] prepend(Class<?> first, Class<?>... rest) {
+ Class<?>[] all = new Class<?>[rest.length+1];
+ all[0] = first;
+ System.arraycopy(rest, 0, all, 1, rest.length);
+ return all;
+ }
+
+ public static class ClassWithSuperclassToWorkAroundCglibBug {}
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java
new file mode 100644
index 0000000..eaa798f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/DelegatingMockitoMethodProxy.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy;
+
+class DelegatingMockitoMethodProxy implements MockitoMethodProxy {
+
+ private final MethodProxy methodProxy;
+
+ public DelegatingMockitoMethodProxy(MethodProxy methodProxy) {
+ this.methodProxy = methodProxy;
+ }
+
+ public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
+ return methodProxy.invokeSuper(target, arguments);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java
new file mode 100644
index 0000000..e8266eb
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MethodInterceptorFilter.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.internal.InternalMockHandler;
+import org.mockito.internal.creation.DelegatingMethod;
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+import org.mockito.internal.invocation.InvocationImpl;
+import org.mockito.internal.invocation.MockitoMethod;
+import org.mockito.internal.invocation.SerializableMethod;
+import org.mockito.internal.invocation.realmethod.CleanTraceRealMethod;
+import org.mockito.internal.progress.SequenceNumber;
+import org.mockito.internal.util.ObjectMethodsGuru;
+import org.mockito.invocation.Invocation;
+import org.mockito.invocation.MockHandler;
+import org.mockito.mock.MockCreationSettings;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodInterceptor;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+
+/**
+ * Should be one instance per mock instance, see CglibMockMaker.
+ */
+public class MethodInterceptorFilter implements MethodInterceptor, Serializable {
+
+ private static final long serialVersionUID = 6182795666612683784L;
+ final ObjectMethodsGuru objectMethodsGuru = new ObjectMethodsGuru();
+ private final InternalMockHandler handler;
+ private final MockCreationSettings mockSettings;
+ private final AcrossJVMSerializationFeature acrossJVMSerializationFeature = new AcrossJVMSerializationFeature();
+
+ public MethodInterceptorFilter(InternalMockHandler handler, MockCreationSettings mockSettings) {
+ this.handler = handler;
+ this.mockSettings = mockSettings;
+ }
+
+ public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)
+ throws Throwable {
+ if (objectMethodsGuru.isEqualsMethod(method)) {
+ return proxy == args[0];
+ } else if (objectMethodsGuru.isHashCodeMethod(method)) {
+ return hashCodeForMock(proxy);
+ } else if (acrossJVMSerializationFeature.isWriteReplace(method)) {
+ return acrossJVMSerializationFeature.writeReplace(proxy);
+ }
+
+ MockitoMethodProxy mockitoMethodProxy = createMockitoMethodProxy(methodProxy);
+ new CGLIBHacker().setMockitoNamingPolicy(methodProxy);
+
+ MockitoMethod mockitoMethod = createMockitoMethod(method);
+
+ CleanTraceRealMethod realMethod = new CleanTraceRealMethod(mockitoMethodProxy);
+ Invocation invocation = new InvocationImpl(proxy, mockitoMethod, args, SequenceNumber.next(), realMethod);
+ return handler.handle(invocation);
+ }
+
+ public MockHandler getHandler() {
+ return handler;
+ }
+
+ private int hashCodeForMock(Object mock) {
+ return System.identityHashCode(mock);
+ }
+
+ public MockitoMethodProxy createMockitoMethodProxy(MethodProxy methodProxy) {
+ if (mockSettings.isSerializable())
+ return new SerializableMockitoMethodProxy(methodProxy);
+ return new DelegatingMockitoMethodProxy(methodProxy);
+ }
+
+ public MockitoMethod createMockitoMethod(Method method) {
+ if (mockSettings.isSerializable()) {
+ return new SerializableMethod(method);
+ } else {
+ return new DelegatingMethod(method);
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt
new file mode 100644
index 0000000..5a311f7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/Mockito-LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License
+
+Copyright (c) 2007 Mockito contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java
new file mode 100644
index 0000000..a540605
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/MockitoNamingPolicy.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.powermock.api.mockito.repackaged.cglib.core.DefaultNamingPolicy;
+
+class MockitoNamingPolicy extends DefaultNamingPolicy {
+
+ public static final MockitoNamingPolicy INSTANCE = new MockitoNamingPolicy();
+
+ @Override
+ protected String getTag() {
+ return "ByMockitoWithCGLIB";
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java
new file mode 100644
index 0000000..614e2c5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableMockitoMethodProxy.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.mockito.internal.creation.util.MockitoMethodProxy;
+import org.mockito.internal.util.reflection.Whitebox;
+import org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy;
+
+import java.io.Serializable;
+
+class SerializableMockitoMethodProxy implements MockitoMethodProxy, Serializable {
+
+ private static final long serialVersionUID = -5337859962876770632L;
+ private final Class<?> c1;
+ private final Class<?> c2;
+ private final String desc;
+ private final String name;
+ private final String superName;
+ transient MethodProxy methodProxy;
+
+ public SerializableMockitoMethodProxy(MethodProxy methodProxy) {
+ assert methodProxy != null;
+ Object info = Whitebox.getInternalState(methodProxy, "createInfo");
+ c1 = (Class<?>) Whitebox.getInternalState(info, "c1");
+ c2 = (Class<?>) Whitebox.getInternalState(info, "c2");
+ desc = methodProxy.getSignature().getDescriptor();
+ name = methodProxy.getSignature().getName();
+ superName = methodProxy.getSuperName();
+ this.methodProxy = methodProxy;
+ }
+
+ MethodProxy getMethodProxy() {
+ if (methodProxy == null) {
+ methodProxy = MethodProxy.create(c1, c2, desc, name, superName);
+ }
+ return methodProxy;
+ }
+
+ public Object invokeSuper(Object target, Object[] arguments) throws Throwable {
+ return getMethodProxy().invokeSuper(target, arguments);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java
new file mode 100644
index 0000000..ffcc918
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/SerializableNoOp.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged;
+
+import org.powermock.api.mockito.repackaged.cglib.proxy.Callback;
+import org.powermock.api.mockito.repackaged.cglib.proxy.NoOp;
+
+import java.io.Serializable;
+
+/**
+ * Offer a Serializable implementation of the NoOp CGLIB callback.
+ */
+class SerializableNoOp implements NoOp, Serializable {
+
+ public static final Callback SERIALIZABLE_INSTANCE = new SerializableNoOp();
+ private static final long serialVersionUID = 7434976328690189159L;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationVisitor.java
new file mode 100644
index 0000000..1dd0ce8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationVisitor.java
@@ -0,0 +1,97 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A visitor to visit a Java annotation. The methods of this interface must be
+ * called in the following order: (<tt>visit<tt> | <tt>visitEnum<tt> |
+ * <tt>visitAnnotation<tt> | <tt>visitArray<tt>)* <tt>visitEnd<tt>.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface AnnotationVisitor {
+
+ /**
+ * Visits a primitive value of the annotation.
+ *
+ * @param name the value name.
+ * @param value the actual value, whose type must be {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type}. This value can also be an array
+ * of byte, boolean, short, char, int, long, float or double values
+ * (this is equivalent to using {@link #visitArray visitArray} and
+ * visiting each array element in turn, but is more convenient).
+ */
+ void visit(String name, Object value);
+
+ /**
+ * Visits an enumeration value of the annotation.
+ *
+ * @param name the value name.
+ * @param desc the class descriptor of the enumeration class.
+ * @param value the actual enumeration value.
+ */
+ void visitEnum(String name, String desc, String value);
+
+ /**
+ * Visits a nested annotation value of the annotation.
+ *
+ * @param name the value name.
+ * @param desc the class descriptor of the nested annotation class.
+ * @return a visitor to visit the actual nested annotation value, or
+ * <tt>null</tt> if this visitor is not interested in visiting
+ * this nested annotation. <i>The nested annotation value must be
+ * fully visited before calling other methods on this annotation
+ * visitor</i>.
+ */
+ AnnotationVisitor visitAnnotation(String name, String desc);
+
+ /**
+ * Visits an array value of the annotation. Note that arrays of primitive
+ * types (such as byte, boolean, short, char, int, long, float or double)
+ * can be passed as value to {@link #visit visit}. This is what
+ * {@link ClassReader} does.
+ *
+ * @param name the value name.
+ * @return a visitor to visit the actual array value elements, or
+ * <tt>null</tt> if this visitor is not interested in visiting
+ * these values. The 'name' parameters passed to the methods of this
+ * visitor are ignored. <i>All the array values must be visited
+ * before calling other methods on this annotation visitor</i>.
+ */
+ AnnotationVisitor visitArray(String name);
+
+ /**
+ * Visits the end of the annotation.
+ */
+ void visitEnd();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationWriter.java
new file mode 100644
index 0000000..816e4b6
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/AnnotationWriter.java
@@ -0,0 +1,309 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+final class AnnotationWriter implements AnnotationVisitor {
+
+ /**
+ * The class writer to which this annotation must be added.
+ */
+ private final ClassWriter cw;
+ /**
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
+ * writers used for annotation default and annotation arrays use unnamed
+ * values.
+ */
+ private final boolean named;
+ /**
+ * The annotation values in bytecode form. This byte vector only contains
+ * the values themselves, i.e. the number of values must be stored as a
+ * unsigned short just before these bytes.
+ */
+ private final ByteVector bv;
+ /**
+ * The byte vector to be used to store the number of values of this
+ * annotation. See {@link #bv}.
+ */
+ private final ByteVector parent;
+ /**
+ * Where the number of values of this annotation must be stored in
+ * {@link #parent}.
+ */
+ private final int offset;
+ /**
+ * Next annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter next;
+ /**
+ * Previous annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter prev;
+ /**
+ * The number of values in this annotation.
+ */
+ private int size;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link AnnotationWriter}.
+ *
+ * @param cw the class writer to which this annotation must be added.
+ * @param named <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+ * @param bv where the annotation values must be stored.
+ * @param parent where the number of annotation values must be stored.
+ * @param offset where in <tt>parent</tt> the number of annotation values must
+ * be stored.
+ */
+ AnnotationWriter(
+ final ClassWriter cw,
+ final boolean named,
+ final ByteVector bv,
+ final ByteVector parent,
+ final int offset)
+ {
+ this.cw = cw;
+ this.named = named;
+ this.bv = bv;
+ this.parent = parent;
+ this.offset = offset;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor interface
+ // ------------------------------------------------------------------------
+
+ /**
+ * Puts the given annotation lists into the given byte vector.
+ *
+ * @param panns an array of annotation writer lists.
+ * @param off index of the first annotation to be written.
+ * @param out where the annotations must be put.
+ */
+ static void put(
+ final AnnotationWriter[] panns,
+ final int off,
+ final ByteVector out)
+ {
+ int size = 1 + 2 * (panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ out.putInt(size).putByte(panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ AnnotationWriter aw = panns[i];
+ AnnotationWriter last = null;
+ int n = 0;
+ while (aw != null) {
+ ++n;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+ }
+
+ public void visit(final String name, final Object value) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ if (value instanceof String) {
+ bv.put12('s', cw.newUTF8((String) value));
+ } else if (value instanceof Byte) {
+ bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
+ } else if (value instanceof Boolean) {
+ int v = ((Boolean) value).booleanValue() ? 1 : 0;
+ bv.put12('Z', cw.newInteger(v).index);
+ } else if (value instanceof Character) {
+ bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
+ } else if (value instanceof Short) {
+ bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
+ } else if (value instanceof Type) {
+ bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
+ } else if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('B', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('S', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('C', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('I', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('J', cw.newLong(v[i]).index);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('F', cw.newFloat(v[i]).index);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('D', cw.newDouble(v[i]).index);
+ }
+ } else {
+ Item i = cw.newConstItem(value);
+ bv.put12(".s.IFJDCS".charAt(i.type), i.index);
+ }
+ }
+
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag and type, and reserve space for values count
+ bv.put12('@', cw.newUTF8(desc)).putShort(0);
+ return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag, and reserve space for array size
+ bv.put12('[', 0);
+ return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ public void visitEnd() {
+ if (parent != null) {
+ byte[] data = parent.data;
+ data[offset] = (byte) (size >>> 8);
+ data[offset + 1] = (byte) size;
+ }
+ }
+
+ /**
+ * Returns the size of this annotation writer list.
+ *
+ * @return the size of this annotation writer list.
+ */
+ int getSize() {
+ int size = 0;
+ AnnotationWriter aw = this;
+ while (aw != null) {
+ size += aw.bv.length;
+ aw = aw.next;
+ }
+ return size;
+ }
+
+ /**
+ * Puts the annotations of this annotation writer list into the given byte
+ * vector.
+ *
+ * @param out where the annotations must be put.
+ */
+ void put(final ByteVector out) {
+ int n = 0;
+ int size = 2;
+ AnnotationWriter aw = this;
+ AnnotationWriter last = null;
+ while (aw != null) {
+ ++n;
+ size += aw.bv.length;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putInt(size);
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Attribute.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Attribute.java
new file mode 100644
index 0000000..a6d4015
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Attribute.java
@@ -0,0 +1,254 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+ /**
+ * The type of this attribute.
+ */
+ public final String type;
+
+ /**
+ * The raw value of this attribute, used only for unknown attributes.
+ */
+ byte[] value;
+
+ /**
+ * The next attribute in this attribute list. May be <tt>null</tt>.
+ */
+ Attribute next;
+
+ /**
+ * Constructs a new empty attribute.
+ *
+ * @param type the type of the attribute.
+ */
+ protected Attribute(final String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is unknown. The default
+ * implementation of this method always returns <tt>true</tt>.
+ *
+ * @return <tt>true</tt> if this type of attribute is unknown.
+ */
+ public boolean isUnknown() {
+ return true;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is a code attribute.
+ *
+ * @return <tt>true</tt> if this type of attribute is a code attribute.
+ */
+ public boolean isCodeAttribute() {
+ return false;
+ }
+
+ /**
+ * Returns the labels corresponding to this attribute.
+ *
+ * @return the labels corresponding to this attribute, or <tt>null</tt> if
+ * this attribute is not a code attribute that contains labels.
+ */
+ protected Label[] getLabels() {
+ return null;
+ }
+
+ /**
+ * Reads a {@link #type type} attribute. This method must return a <i>new</i>
+ * {@link Attribute} object, of type {@link #type type}, corresponding to
+ * the <tt>len</tt> bytes starting at the given offset, in the given class
+ * reader.
+ *
+ * @param cr the class that contains the attribute to be read.
+ * @param off index of the first byte of the attribute's content in {@link
+ * ClassReader#b cr.b}. The 6 attribute header bytes, containing the
+ * type and the length of the attribute, are not taken into account
+ * here.
+ * @param len the length of the attribute's content.
+ * @param buf buffer to be used to call
+ * {@link ClassReader#readUTF8 readUTF8},
+ * {@link ClassReader#readClass(int,char[]) readClass} or
+ * {@link ClassReader#readConst readConst}.
+ * @param codeOff index of the first byte of code's attribute content in
+ * {@link ClassReader#b cr.b}, or -1 if the attribute to be read is
+ * not a code attribute. The 6 attribute header bytes, containing the
+ * type and the length of the attribute, are not taken into account
+ * here.
+ * @param labels the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return a <i>new</i> {@link Attribute} object corresponding to the given
+ * bytes.
+ */
+ protected Attribute read(
+ final ClassReader cr,
+ final int off,
+ final int len,
+ final char[] buf,
+ final int codeOff,
+ final Label[] labels)
+ {
+ Attribute attr = new Attribute(type);
+ attr.value = new byte[len];
+ System.arraycopy(cr.b, off, attr.value, 0, len);
+ return attr;
+ }
+
+ /**
+ * Returns the byte array form of this attribute.
+ *
+ * @param cw the class to which this attribute must be added. This parameter
+ * can be used to add to the constant pool of this class the items
+ * that corresponds to this attribute.
+ * @param code the bytecode of the method corresponding to this code
+ * attribute, or <tt>null</tt> if this attribute is not a code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to this
+ * code attribute, or <tt>null</tt> if this attribute is not a code
+ * attribute.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * this code attribute, or -1 if this attribute is not a code
+ * attribute.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to this code attribute, or -1 if this attribute is
+ * not a code attribute.
+ * @return the byte array form of this attribute.
+ */
+ protected ByteVector write(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals)
+ {
+ ByteVector v = new ByteVector();
+ v.data = value;
+ v.length = value.length;
+ return v;
+ }
+
+ /**
+ * Returns the length of the attribute list that begins with this attribute.
+ *
+ * @return the length of the attribute list that begins with this attribute.
+ */
+ final int getCount() {
+ int count = 0;
+ Attribute attr = this;
+ while (attr != null) {
+ count += 1;
+ attr = attr.next;
+ }
+ return count;
+ }
+
+ /**
+ * Returns the size of all the attributes in this attribute list.
+ *
+ * @param cw the class writer to be used to convert the attributes into byte
+ * arrays, with the {@link #write write} method.
+ * @param code the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes are
+ * not code attributes.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * these code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these attributes
+ * are not code attributes.
+ * @return the size of all the attributes in this attribute list. This size
+ * includes the size of the attribute headers.
+ */
+ final int getSize(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals)
+ {
+ Attribute attr = this;
+ int size = 0;
+ while (attr != null) {
+ cw.newUTF8(attr.type);
+ size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
+ attr = attr.next;
+ }
+ return size;
+ }
+
+ /**
+ * Writes all the attributes of this attribute list in the given byte
+ * vector.
+ *
+ * @param cw the class writer to be used to convert the attributes into byte
+ * arrays, with the {@link #write write} method.
+ * @param code the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes are
+ * not code attributes.
+ * @param maxStack the maximum stack size of the method corresponding to
+ * these code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these attributes
+ * are not code attributes.
+ * @param out where the attributes must be written.
+ */
+ final void put(
+ final ClassWriter cw,
+ final byte[] code,
+ final int len,
+ final int maxStack,
+ final int maxLocals,
+ final ByteVector out)
+ {
+ Attribute attr = this;
+ while (attr != null) {
+ ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
+ out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
+ out.putByteArray(b.data, 0, b.length);
+ attr = attr.next;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ByteVector.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ByteVector.java
new file mode 100644
index 0000000..b01bea6
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ByteVector.java
@@ -0,0 +1,293 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ *
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+ /**
+ * The content of this vector.
+ */
+ byte[] data;
+
+ /**
+ * Actual number of bytes in this vector.
+ */
+ int length;
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with a default initial
+ * size.
+ */
+ public ByteVector() {
+ data = new byte[64];
+ }
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with the given initial
+ * size.
+ *
+ * @param initialSize the initial size of the byte vector to be constructed.
+ */
+ public ByteVector(final int initialSize) {
+ data = new byte[initialSize];
+ }
+
+ /**
+ * Puts a byte into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b a byte.
+ * @return this byte vector.
+ */
+ public ByteVector putByte(final int b) {
+ int length = this.length;
+ if (length + 1 > data.length) {
+ enlarge(1);
+ }
+ data[length++] = (byte) b;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts two bytes into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b1 a byte.
+ * @param b2 another byte.
+ * @return this byte vector.
+ */
+ ByteVector put11(final int b1, final int b2) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b1;
+ data[length++] = (byte) b2;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a short into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param s a short.
+ * @return this byte vector.
+ */
+ public ByteVector putShort(final int s) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a byte and a short into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b a byte.
+ * @param s a short.
+ * @return this byte vector.
+ */
+ ByteVector put12(final int b, final int s) {
+ int length = this.length;
+ if (length + 3 > data.length) {
+ enlarge(3);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an int into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param i an int.
+ * @return this byte vector.
+ */
+ public ByteVector putInt(final int i) {
+ int length = this.length;
+ if (length + 4 > data.length) {
+ enlarge(4);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a long into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param l a long.
+ * @return this byte vector.
+ */
+ public ByteVector putLong(final long l) {
+ int length = this.length;
+ if (length + 8 > data.length) {
+ enlarge(8);
+ }
+ byte[] data = this.data;
+ int i = (int) (l >>> 32);
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ i = (int) l;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param s a String.
+ * @return this byte vector.
+ */
+ public ByteVector putUTF8(final String s) {
+ int charLength = s.length();
+ if (length + 2 + charLength > data.length) {
+ enlarge(2 + charLength);
+ }
+ int len = length;
+ byte[] data = this.data;
+ // optimistic algorithm: instead of computing the byte length and then
+ // serializing the string (which requires two loops), we assume the byte
+ // length is equal to char length (which is the most frequent case), and
+ // we start serializing the string right away. During the serialization,
+ // if we find that this assumption is wrong, we continue with the
+ // general method.
+ data[len++] = (byte) (charLength >>> 8);
+ data[len++] = (byte) charLength;
+ for (int i = 0; i < charLength; ++i) {
+ char c = s.charAt(i);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else {
+ int byteLength = i;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ data[length] = (byte) (byteLength >>> 8);
+ data[length + 1] = (byte) byteLength;
+ if (length + 2 + byteLength > data.length) {
+ length = len;
+ enlarge(2 + byteLength);
+ data = this.data;
+ }
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ }
+ }
+ break;
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an array of bytes into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+ * null bytes into this byte vector.
+ * @param off index of the fist byte of b that must be copied.
+ * @param len number of bytes of b that must be copied.
+ * @return this byte vector.
+ */
+ public ByteVector putByteArray(final byte[] b, final int off, final int len)
+ {
+ if (length + len > data.length) {
+ enlarge(len);
+ }
+ if (b != null) {
+ System.arraycopy(b, off, data, length, len);
+ }
+ length += len;
+ return this;
+ }
+
+ /**
+ * Enlarge this byte vector so that it can receive n more bytes.
+ *
+ * @param size number of additional bytes that this byte vector should be
+ * able to receive.
+ */
+ private void enlarge(final int size) {
+ int length1 = 2 * data.length;
+ int length2 = length + size;
+ byte[] newData = new byte[length1 > length2 ? length1 : length2];
+ System.arraycopy(data, 0, newData, 0, length);
+ data = newData;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassAdapter.java
new file mode 100644
index 0000000..35f4891
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassAdapter.java
@@ -0,0 +1,121 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * An empty {@link ClassVisitor} that delegates to another {@link ClassVisitor}.
+ * This class can be used as a super class to quickly implement usefull class
+ * adapter classes, just by overriding the necessary methods.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassAdapter implements ClassVisitor {
+
+ /**
+ * The {@link ClassVisitor} to which this adapter delegates calls.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Constructs a new {@link ClassAdapter} object.
+ *
+ * @param cv the class visitor to which this adapter must delegate calls.
+ */
+ public ClassAdapter(final ClassVisitor cv) {
+ this.cv = cv;
+ }
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ public void visitSource(final String source, final String debug) {
+ cv.visitSource(source, debug);
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ cv.visitOuterClass(owner, name, desc);
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return cv.visitAnnotation(desc, visible);
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ cv.visitAttribute(attr);
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ return cv.visitField(access, name, desc, signature, value);
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ return cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ public void visitEnd() {
+ cv.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassReader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassReader.java
new file mode 100644
index 0000000..d4743a1
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassReader.java
@@ -0,0 +1,1996 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+ /**
+ * Flag to skip method code. If this class is set <code>CODE</code>
+ * attribute won't be visited. This can be used, for example, to retrieve
+ * annotations for methods and method parameters.
+ */
+ public static final int SKIP_CODE = 1;
+ /**
+ * Flag to skip the debug information in the class. If this flag is set the
+ * debug information of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+ * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+ * called.
+ */
+ public static final int SKIP_DEBUG = 2;
+ /**
+ * Flag to skip the stack map frames in the class. If this flag is set the
+ * stack map frames of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+ * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+ * used: it avoids visiting frames that will be ignored and recomputed from
+ * scratch in the class writer.
+ */
+ public static final int SKIP_FRAMES = 4;
+ /**
+ * Flag to expand the stack map frames. By default stack map frames are
+ * visited in their original format (i.e. "expanded" for classes whose
+ * version is less than V1_6, and "compressed" for the other classes). If
+ * this flag is set, stack map frames are always visited in expanded format
+ * (this option adds a decompression/recompression step in ClassReader and
+ * ClassWriter which degrades performances quite a lot).
+ */
+ public static final int EXPAND_FRAMES = 8;
+ /**
+ * True to enable signatures support.
+ */
+ static final boolean SIGNATURES = true;
+ /**
+ * True to enable annotations support.
+ */
+ static final boolean ANNOTATIONS = true;
+ /**
+ * True to enable stack map frames support.
+ */
+ static final boolean FRAMES = true;
+ /**
+ * True to enable bytecode writing support.
+ */
+ static final boolean WRITER = true;
+ /**
+ * True to enable JSR_W and GOTO_W support.
+ */
+ static final boolean RESIZE = true;
+ /**
+ * The class to be parsed. <i>The content of this array must not be
+ * modified. This field is intended for {@link Attribute} sub classes, and
+ * is normally not needed by class generators or adapters.</i>
+ */
+ public final byte[] b;
+ /**
+ * Start index of the class header information (access, name...) in
+ * {@link #b b}.
+ */
+ public final int header;
+ /**
+ * The start index of each constant pool item in {@link #b b}, plus one.
+ * The one byte offset skips the constant pool item tag that indicates its
+ * type.
+ */
+ private final int[] items;
+ /**
+ * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+ * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+ * which GREATLY improves performances (by a factor 2 to 3). This caching
+ * strategy could be extended to all constant pool items, but its benefit
+ * would not be so great for these items (because they are much less
+ * expensive to parse than CONSTANT_Utf8 items).
+ */
+ private final String[] strings;
+ /**
+ * Maximum length of the strings contained in the constant pool of the
+ * class.
+ */
+ private final int maxStringLength;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ */
+ public ClassReader(final byte[] b) {
+ this(b, 0, b.length);
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b the bytecode of the class to be read.
+ * @param off the start offset of the class data.
+ * @param len the length of the class data.
+ */
+ public ClassReader(final byte[] b, final int off, final int len) {
+ this.b = b;
+ // parses the constant pool
+ items = new int[readUnsignedShort(off + 8)];
+ int n = items.length;
+ strings = new String[n];
+ int max = 0;
+ int index = off + 10;
+ for (int i = 1; i < n; ++i) {
+ items[i] = index + 1;
+ int size;
+ switch (b[index]) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ case ClassWriter.NAME_TYPE:
+ size = 5;
+ break;
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8:
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max) {
+ max = size;
+ }
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ default:
+ size = 3;
+ break;
+ }
+ index += size;
+ }
+ maxStringLength = max;
+ // the class header information starts just after the constant pool
+ header = index;
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param is an input stream from which to read the class.
+ * @throws IOException if a problem occurs during reading.
+ */
+ public ClassReader(final InputStream is) throws IOException {
+ this(readClass(is));
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param name the fully qualified name of the class to be read.
+ * @throws IOException if an exception occurs during reading.
+ */
+ public ClassReader(final String name) throws IOException {
+ this(ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ + ".class"));
+ }
+
+ /**
+ * Reads the bytecode of a class.
+ *
+ * @param is an input stream from which to read the class.
+ * @return the bytecode read from the given input stream.
+ * @throws IOException if a problem occurs during reading.
+ */
+ private static byte[] readClass(final InputStream is) throws IOException {
+ if (is == null) {
+ throw new IOException("Class not found");
+ }
+ byte[] b = new byte[is.available()];
+ int len = 0;
+ while (true) {
+ int n = is.read(b, len, b.length - len);
+ if (n == -1) {
+ if (len < b.length) {
+ byte[] c = new byte[len];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ return b;
+ }
+ len += n;
+ if (len == b.length) {
+ byte[] c = new byte[b.length + 1000];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ }
+ }
+
+ /**
+ * Returns the class's access flags (see {@link Opcodes}). This value may
+ * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+ * and those flags are represented by attributes.
+ *
+ * @return the class access flags
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public int getAccess() {
+ return readUnsignedShort(header);
+ }
+
+ /**
+ * Returns the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the internal class name
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getClassName() {
+ return readClass(header + 2, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces, the
+ * super class is {@link Object}.
+ *
+ * @return the internal name of super class, or <tt>null</tt> for
+ * {@link Object} class.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getSuperName() {
+ int n = items[readUnsignedShort(header + 4)];
+ return n == 0 ? null : readUTF8(n, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the array of internal names for all implemented interfaces or
+ * <tt>null</tt>.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String[] getInterfaces() {
+ int index = header + 6;
+ int n = readUnsignedShort(index);
+ String[] interfaces = new String[n];
+ if (n > 0) {
+ char[] buf = new char[maxStringLength];
+ for (int i = 0; i < n; ++i) {
+ index += 2;
+ interfaces[i] = readClass(index, buf);
+ }
+ }
+ return interfaces;
+ }
+
+ /**
+ * Copies the constant pool data into the given {@link ClassWriter}. Should
+ * be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter the {@link ClassWriter} to copy constant pool into.
+ */
+ void copyPool(final ClassWriter classWriter) {
+ char[] buf = new char[maxStringLength];
+ int ll = items.length;
+ Item[] items2 = new Item[ll];
+ for (int i = 1; i < ll; i++) {
+ int index = items[i];
+ int tag = b[index - 1];
+ Item item = new Item(i);
+ int nameType;
+ switch (tag) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag,
+ readClass(index, buf),
+ readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+ break;
+
+ case ClassWriter.INT:
+ item.set(readInt(index));
+ break;
+
+ case ClassWriter.FLOAT:
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+
+ case ClassWriter.NAME_TYPE:
+ item.set(tag,
+ readUTF8(index, buf),
+ readUTF8(index + 2, buf),
+ null);
+ break;
+
+ case ClassWriter.LONG:
+ item.set(readLong(index));
+ ++i;
+ break;
+
+ case ClassWriter.DOUBLE:
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+
+ case ClassWriter.UTF8: {
+ String s = strings[i];
+ if (s == null) {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2,
+ readUnsignedShort(index),
+ buf);
+ }
+ item.set(tag, s, null, null);
+ }
+ break;
+
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ default:
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
+ }
+
+ int index2 = item.hashCode % items2.length;
+ item.next = items2[index2];
+ items2[index2] = item;
+ }
+
+ int off = items[1] - 1;
+ classWriter.pool.putByteArray(b, off, header - off);
+ classWriter.items = items2;
+ classWriter.threshold = (int) (0.75d * ll);
+ classWriter.index = ll;
+ }
+
+ // ------------------------------------------------------------------------
+ // Public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor, final int flags) {
+ accept(classVisitor, new Attribute[0], flags);
+ }
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor the visitor that must visit this class.
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes will not be parsed: its byte array
+ * value will be passed unchanged to the ClassWriter. <i>This may
+ * corrupt it if this value contains references to the constant pool,
+ * or has syntactic or semantic links with a class element that has
+ * been transformed by a class adapter between the reader and the
+ * writer</i>.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES},
+ * {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(
+ final ClassVisitor classVisitor,
+ final Attribute[] attrs,
+ final int flags)
+ {
+ byte[] b = this.b; // the bytecode array
+ char[] c = new char[maxStringLength]; // buffer used to read strings
+ int i, j, k; // loop variables
+ int u, v, w; // indexes in b
+ Attribute attr;
+
+ int access;
+ String name;
+ String desc;
+ String attrName;
+ String signature;
+ int anns = 0;
+ int ianns = 0;
+ Attribute cattrs = null;
+
+ // visits the header
+ u = header;
+ access = readUnsignedShort(u);
+ name = readClass(u + 2, c);
+ v = items[readUnsignedShort(u + 4)];
+ String superClassName = v == 0 ? null : readUTF8(v, c);
+ String[] implementedItfs = new String[readUnsignedShort(u + 6)];
+ w = 0;
+ u += 8;
+ for (i = 0; i < implementedItfs.length; ++i) {
+ implementedItfs[i] = readClass(u, c);
+ u += 2;
+ }
+
+ boolean skipCode = (flags & SKIP_CODE) != 0;
+ boolean skipDebug = (flags & SKIP_DEBUG) != 0;
+ boolean unzip = (flags & EXPAND_FRAMES) != 0;
+
+ // skips fields and methods
+ v = u;
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ j = readUnsignedShort(v + 6);
+ v += 8;
+ for (; j > 0; --j) {
+ v += 6 + readInt(v + 2);
+ }
+ }
+ // reads the class's attributes
+ signature = null;
+ String sourceFile = null;
+ String sourceDebug = null;
+ String enclosingOwner = null;
+ String enclosingName = null;
+ String enclosingDesc = null;
+
+ i = readUnsignedShort(v);
+ v += 2;
+ for (; i > 0; --i) {
+ attrName = readUTF8(v, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("SourceFile".equals(attrName)) {
+ sourceFile = readUTF8(v + 6, c);
+ } else if ("InnerClasses".equals(attrName)) {
+ w = v + 6;
+ } else if ("EnclosingMethod".equals(attrName)) {
+ enclosingOwner = readClass(v + 6, c);
+ int item = readUnsignedShort(v + 8);
+ if (item != 0) {
+ enclosingName = readUTF8(items[item], c);
+ enclosingDesc = readUTF8(items[item] + 2, c);
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(v + 6, c);
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = v + 6;
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC;
+ } else if ("SourceDebugExtension".equals(attrName)) {
+ int len = readInt(v + 2);
+ sourceDebug = readUTF(v + 6, len, new char[len]);
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = v + 6;
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ v + 6,
+ readInt(v + 2),
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ v += 6 + readInt(v + 2);
+ }
+ // calls the visit method
+ classVisitor.visit(readInt(4),
+ access,
+ name,
+ signature,
+ superClassName,
+ implementedItfs);
+
+ // calls the visitSource method
+ if (!skipDebug && (sourceFile != null || sourceDebug != null)) {
+ classVisitor.visitSource(sourceFile, sourceDebug);
+ }
+
+ // calls the visitOuterClass method
+ if (enclosingOwner != null) {
+ classVisitor.visitOuterClass(enclosingOwner,
+ enclosingName,
+ enclosingDesc);
+ }
+
+ // visits the class annotations
+ if (ANNOTATIONS) {
+ for (i = 1; i >= 0; --i) {
+ v = i == 0 ? ianns : anns;
+ if (v != 0) {
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ v = readAnnotationValues(v + 2,
+ c,
+ true,
+ classVisitor.visitAnnotation(readUTF8(v, c), i != 0));
+ }
+ }
+ }
+ }
+
+ // visits the class attributes
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ classVisitor.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+
+ // calls the visitInnerClass method
+ if (w != 0) {
+ i = readUnsignedShort(w);
+ w += 2;
+ for (; i > 0; --i) {
+ classVisitor.visitInnerClass(readUnsignedShort(w) == 0
+ ? null
+ : readClass(w, c), readUnsignedShort(w + 2) == 0
+ ? null
+ : readClass(w + 2, c), readUnsignedShort(w + 4) == 0
+ ? null
+ : readUTF8(w + 4, c), readUnsignedShort(w + 6));
+ w += 8;
+ }
+ }
+
+ // visits the fields
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i) {
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ // visits the field's attributes and looks for a ConstantValue
+ // attribute
+ int fieldValueItem = 0;
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ cattrs = null;
+
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j) {
+ attrName = readUTF8(u, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName)) {
+ fieldValueItem = readUnsignedShort(u + 6);
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 6, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC;
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 6;
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 6;
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ u + 6,
+ readInt(u + 2),
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += 6 + readInt(u + 2);
+ }
+ // visits the field
+ FieldVisitor fv = classVisitor.visitField(access,
+ name,
+ desc,
+ signature,
+ fieldValueItem == 0 ? null : readConst(fieldValueItem, c));
+ // visits the field annotations and attributes
+ if (fv != null) {
+ if (ANNOTATIONS) {
+ for (j = 1; j >= 0; --j) {
+ v = j == 0 ? ianns : anns;
+ if (v != 0) {
+ k = readUnsignedShort(v);
+ v += 2;
+ for (; k > 0; --k) {
+ v = readAnnotationValues(v + 2,
+ c,
+ true,
+ fv.visitAnnotation(readUTF8(v, c), j != 0));
+ }
+ }
+ }
+ }
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ fv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ fv.visitEnd();
+ }
+ }
+
+ // visits the methods
+ i = readUnsignedShort(u);
+ u += 2;
+ for (; i > 0; --i) {
+ int u0 = u + 6;
+ access = readUnsignedShort(u);
+ name = readUTF8(u + 2, c);
+ desc = readUTF8(u + 4, c);
+ signature = null;
+ anns = 0;
+ ianns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ cattrs = null;
+ v = 0;
+ w = 0;
+
+ // looks for Code and Exceptions attributes
+ j = readUnsignedShort(u + 6);
+ u += 8;
+ for (; j > 0; --j) {
+ attrName = readUTF8(u, c);
+ int attrSize = readInt(u + 2);
+ u += 6;
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName)) {
+ if (!skipCode) {
+ v = u;
+ }
+ } else if ("Exceptions".equals(attrName)) {
+ w = u;
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if (ANNOTATIONS && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u;
+ } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+ dann = u;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC;
+ } else if (ANNOTATIONS && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u;
+ } else if (ANNOTATIONS && "RuntimeVisibleParameterAnnotations".equals(attrName))
+ {
+ mpanns = u;
+ } else if (ANNOTATIONS && "RuntimeInvisibleParameterAnnotations".equals(attrName))
+ {
+ impanns = u;
+ } else {
+ attr = readAttribute(attrs,
+ attrName,
+ u,
+ attrSize,
+ c,
+ -1,
+ null);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ u += attrSize;
+ }
+ // reads declared exceptions
+ String[] exceptions;
+ if (w == 0) {
+ exceptions = null;
+ } else {
+ exceptions = new String[readUnsignedShort(w)];
+ w += 2;
+ for (j = 0; j < exceptions.length; ++j) {
+ exceptions[j] = readClass(w, c);
+ w += 2;
+ }
+ }
+
+ // visits the method's code, if any
+ MethodVisitor mv = classVisitor.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+
+ if (mv != null) {
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it
+ * means there is no method adapter between the reader and the
+ * writer. If, in addition, the writer's constant pool was
+ * copied from this reader (mw.cw.cr == this), and the signature
+ * and exceptions of the method have not been changed, then it
+ * is possible to skip all visit events and just copy the
+ * original code of the method to the writer (the access, name
+ * and descriptor can have been changed, this is not important
+ * since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter) {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this) {
+ if (signature == mw.signature) {
+ boolean sameExceptions = false;
+ if (exceptions == null) {
+ sameExceptions = mw.exceptionCount == 0;
+ } else {
+ if (exceptions.length == mw.exceptionCount) {
+ sameExceptions = true;
+ for (j = exceptions.length - 1; j >= 0; --j)
+ {
+ w -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(w))
+ {
+ sameExceptions = false;
+ break;
+ }
+ }
+ }
+ }
+ if (sameExceptions) {
+ /*
+ * we do not copy directly the code into
+ * MethodWriter to save a byte array copy
+ * operation. The real copy will be done in
+ * ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = u0;
+ mw.classReaderLength = u - u0;
+ continue;
+ }
+ }
+ }
+ }
+
+ if (ANNOTATIONS && dann != 0) {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null) {
+ dv.visitEnd();
+ }
+ }
+ if (ANNOTATIONS) {
+ for (j = 1; j >= 0; --j) {
+ w = j == 0 ? ianns : anns;
+ if (w != 0) {
+ k = readUnsignedShort(w);
+ w += 2;
+ for (; k > 0; --k) {
+ w = readAnnotationValues(w + 2,
+ c,
+ true,
+ mv.visitAnnotation(readUTF8(w, c), j != 0));
+ }
+ }
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0) {
+ readParameterAnnotations(mpanns, desc, c, true, mv);
+ }
+ if (ANNOTATIONS && impanns != 0) {
+ readParameterAnnotations(impanns, desc, c, false, mv);
+ }
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ }
+
+ if (mv != null && v != 0) {
+ int maxStack = readUnsignedShort(v);
+ int maxLocals = readUnsignedShort(v + 2);
+ int codeLength = readInt(v + 4);
+ v += 8;
+
+ int codeStart = v;
+ int codeEnd = v + codeLength;
+
+ mv.visitCode();
+
+ // 1st phase: finds the labels
+ int label;
+ Label[] labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (v < codeEnd) {
+ w = v - codeStart;
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ readLabel(w + readShort(v + 1), labels);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ readLabel(w + readInt(v + 1), labels);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ v += 6;
+ } else {
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 8) - readInt(v + 4) + 1;
+ v += 12;
+ for (; j > 0; --j) {
+ readLabel(w + readInt(v), labels);
+ v += 4;
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes*
+ v = v + 4 - (w & 3);
+ // reads instruction
+ readLabel(w + readInt(v), labels);
+ j = readInt(v + 4);
+ v += 8;
+ for (; j > 0; --j) {
+ readLabel(w + readInt(v + 4), labels);
+ v += 8;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ v += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ v += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ v += 4;
+ break;
+ }
+ }
+ // parses the try catch entries
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ Label start = readLabel(readUnsignedShort(v), labels);
+ Label end = readLabel(readUnsignedShort(v + 2), labels);
+ Label handler = readLabel(readUnsignedShort(v + 4), labels);
+ int type = readUnsignedShort(v + 6);
+ if (type == 0) {
+ mv.visitTryCatchBlock(start, end, handler, null);
+ } else {
+ mv.visitTryCatchBlock(start,
+ end,
+ handler,
+ readUTF8(items[type], c));
+ }
+ v += 8;
+ }
+ // parses the local variable, line number tables, and code
+ // attributes
+ int varTable = 0;
+ int varTypeTable = 0;
+ int stackMap = 0;
+ int frameCount = 0;
+ int frameMode = 0;
+ int frameOffset = 0;
+ int frameLocalCount = 0;
+ int frameLocalDiff = 0;
+ int frameStackCount = 0;
+ Object[] frameLocal = null;
+ Object[] frameStack = null;
+ boolean zip = true;
+ cattrs = null;
+ j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ attrName = readUTF8(v, c);
+ if ("LocalVariableTable".equals(attrName)) {
+ if (!skipDebug) {
+ varTable = v + 6;
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k) {
+ label = readUnsignedShort(w);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ label += readUnsignedShort(w + 2);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ w += 10;
+ }
+ }
+ } else if ("LocalVariableTypeTable".equals(attrName)) {
+ varTypeTable = v + 6;
+ } else if ("LineNumberTable".equals(attrName)) {
+ if (!skipDebug) {
+ k = readUnsignedShort(v + 6);
+ w = v + 8;
+ for (; k > 0; --k) {
+ label = readUnsignedShort(w);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ labels[label].line = readUnsignedShort(w + 2);
+ w += 4;
+ }
+ }
+ } else if (FRAMES && "StackMapTable".equals(attrName)) {
+ if ((flags & SKIP_FRAMES) == 0) {
+ stackMap = v + 8;
+ frameCount = readUnsignedShort(v + 6);
+ }
+ /*
+ * here we do not extract the labels corresponding to
+ * the attribute content. This would require a full
+ * parsing of the attribute, which would need to be
+ * repeated in the second phase (see below). Instead the
+ * content of the attribute is read one frame at a time
+ * (i.e. after a frame has been visited, the next frame
+ * is read), and the labels it contains are also
+ * extracted one frame at a time. Thanks to the ordering
+ * of frames, having only a "one frame lookahead" is not
+ * a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for
+ * which no Label exist.
+ */
+ // TODO true for frame offsets,
+ // but for UNINITIALIZED type offsets?
+ } else if (FRAMES && "StackMap".equals(attrName)) {
+ if ((flags & SKIP_FRAMES) == 0) {
+ stackMap = v + 8;
+ frameCount = readUnsignedShort(v + 6);
+ zip = false;
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are
+ * ordered, as in the StackMapTable attribute, although
+ * this is not guaranteed by the attribute format.
+ */
+ } else {
+ for (k = 0; k < attrs.length; ++k) {
+ if (attrs[k].type.equals(attrName)) {
+ attr = attrs[k].read(this,
+ v + 6,
+ readInt(v + 2),
+ c,
+ codeStart - 8,
+ labels);
+ if (attr != null) {
+ attr.next = cattrs;
+ cattrs = attr;
+ }
+ }
+ }
+ }
+ v += 6 + readInt(v + 2);
+ }
+
+ // 2nd phase: visits each instruction
+ if (FRAMES && stackMap != 0) {
+ // creates the very first (implicit) frame from the method
+ // descriptor
+ frameLocal = new Object[maxLocals];
+ frameStack = new Object[maxStack];
+ if (unzip) {
+ int local = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(name)) {
+ frameLocal[local++] = Opcodes.UNINITIALIZED_THIS;
+ } else {
+ frameLocal[local++] = readClass(header + 2, c);
+ }
+ }
+ j = 1;
+ loop: while (true) {
+ k = j;
+ switch (desc.charAt(j++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ frameLocal[local++] = Opcodes.INTEGER;
+ break;
+ case 'F':
+ frameLocal[local++] = Opcodes.FLOAT;
+ break;
+ case 'J':
+ frameLocal[local++] = Opcodes.LONG;
+ break;
+ case 'D':
+ frameLocal[local++] = Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (desc.charAt(j) == '[') {
+ ++j;
+ }
+ if (desc.charAt(j) == 'L') {
+ ++j;
+ while (desc.charAt(j) != ';') {
+ ++j;
+ }
+ }
+ frameLocal[local++] = desc.substring(k, ++j);
+ break;
+ case 'L':
+ while (desc.charAt(j) != ';') {
+ ++j;
+ }
+ frameLocal[local++] = desc.substring(k + 1,
+ j++);
+ break;
+ default:
+ break loop;
+ }
+ }
+ frameLocalCount = local;
+ }
+ /*
+ * for the first explicit frame the offset is not
+ * offset_delta + 1 but only offset_delta; setting the
+ * implicit frame offset to -1 allow the use of the
+ * "offset_delta + 1" rule in all cases
+ */
+ frameOffset = -1;
+ }
+ v = codeStart;
+ Label l;
+ while (v < codeEnd) {
+ w = v - codeStart;
+
+ l = labels[w];
+ if (l != null) {
+ mv.visitLabel(l);
+ if (!skipDebug && l.line > 0) {
+ mv.visitLineNumber(l.line, l);
+ }
+ }
+
+ while (FRAMES && frameLocal != null
+ && (frameOffset == w || frameOffset == -1))
+ {
+ // if there is a frame for this offset,
+ // makes the visitor visit it,
+ // and reads the next frame if there is one.
+ if (!zip || unzip) {
+ mv.visitFrame(Opcodes.F_NEW,
+ frameLocalCount,
+ frameLocal,
+ frameStackCount,
+ frameStack);
+ } else if (frameOffset != -1) {
+ mv.visitFrame(frameMode,
+ frameLocalDiff,
+ frameLocal,
+ frameStackCount,
+ frameStack);
+ }
+
+ if (frameCount > 0) {
+ int tag, delta, n;
+ if (zip) {
+ tag = b[stackMap++] & 0xFF;
+ } else {
+ tag = MethodWriter.FULL_FRAME;
+ frameOffset = -1;
+ }
+ frameLocalDiff = 0;
+ if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME)
+ {
+ delta = tag;
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
+ } else if (tag < MethodWriter.RESERVED) {
+ delta = tag
+ - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+ stackMap = readFrameType(frameStack,
+ 0,
+ stackMap,
+ c,
+ labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
+ } else {
+ delta = readUnsignedShort(stackMap);
+ stackMap += 2;
+ if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ {
+ stackMap = readFrameType(frameStack,
+ 0,
+ stackMap,
+ c,
+ labels);
+ frameMode = Opcodes.F_SAME1;
+ frameStackCount = 1;
+ } else if (tag >= MethodWriter.CHOP_FRAME
+ && tag < MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_CHOP;
+ frameLocalDiff = MethodWriter.SAME_FRAME_EXTENDED
+ - tag;
+ frameLocalCount -= frameLocalDiff;
+ frameStackCount = 0;
+ } else if (tag == MethodWriter.SAME_FRAME_EXTENDED)
+ {
+ frameMode = Opcodes.F_SAME;
+ frameStackCount = 0;
+ } else if (tag < MethodWriter.FULL_FRAME) {
+ j = unzip ? frameLocalCount : 0;
+ for (k = tag
+ - MethodWriter.SAME_FRAME_EXTENDED; k > 0; k--)
+ {
+ stackMap = readFrameType(frameLocal,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ frameMode = Opcodes.F_APPEND;
+ frameLocalDiff = tag
+ - MethodWriter.SAME_FRAME_EXTENDED;
+ frameLocalCount += frameLocalDiff;
+ frameStackCount = 0;
+ } else { // if (tag == FULL_FRAME) {
+ frameMode = Opcodes.F_FULL;
+ n = frameLocalDiff = frameLocalCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--) {
+ stackMap = readFrameType(frameLocal,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ n = frameStackCount = readUnsignedShort(stackMap);
+ stackMap += 2;
+ for (j = 0; n > 0; n--) {
+ stackMap = readFrameType(frameStack,
+ j++,
+ stackMap,
+ c,
+ labels);
+ }
+ }
+ }
+ frameOffset += delta + 1;
+ readLabel(frameOffset, labels);
+
+ --frameCount;
+ } else {
+ frameLocal = null;
+ }
+ }
+
+ int opcode = b[v] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ mv.visitInsn(opcode);
+ v += 1;
+ break;
+ case ClassWriter.IMPLVAR_INSN:
+ if (opcode > Opcodes.ISTORE) {
+ opcode -= 59; // ISTORE_0
+ mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
+ opcode & 0x3);
+ } else {
+ opcode -= 26; // ILOAD_0
+ mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2),
+ opcode & 0x3);
+ }
+ v += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ mv.visitJumpInsn(opcode, labels[w
+ + readShort(v + 1)]);
+ v += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ mv.visitJumpInsn(opcode - 33, labels[w
+ + readInt(v + 1)]);
+ v += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[v + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ mv.visitIincInsn(readUnsignedShort(v + 2),
+ readShort(v + 4));
+ v += 6;
+ } else {
+ mv.visitVarInsn(opcode,
+ readUnsignedShort(v + 2));
+ v += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ int min = readInt(v + 4);
+ int max = readInt(v + 8);
+ v += 12;
+ Label[] table = new Label[max - min + 1];
+ for (j = 0; j < table.length; ++j) {
+ table[j] = labels[w + readInt(v)];
+ v += 4;
+ }
+ mv.visitTableSwitchInsn(min,
+ max,
+ labels[label],
+ table);
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = v + 4 - (w & 3);
+ // reads instruction
+ label = w + readInt(v);
+ j = readInt(v + 4);
+ v += 8;
+ int[] keys = new int[j];
+ Label[] values = new Label[j];
+ for (j = 0; j < keys.length; ++j) {
+ keys[j] = readInt(v);
+ values[j] = labels[w + readInt(v + 4)];
+ v += 8;
+ }
+ mv.visitLookupSwitchInsn(labels[label],
+ keys,
+ values);
+ break;
+ case ClassWriter.VAR_INSN:
+ mv.visitVarInsn(opcode, b[v + 1] & 0xFF);
+ v += 2;
+ break;
+ case ClassWriter.SBYTE_INSN:
+ mv.visitIntInsn(opcode, b[v + 1]);
+ v += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ mv.visitIntInsn(opcode, readShort(v + 1));
+ v += 3;
+ break;
+ case ClassWriter.LDC_INSN:
+ mv.visitLdcInsn(readConst(b[v + 1] & 0xFF, c));
+ v += 2;
+ break;
+ case ClassWriter.LDCW_INSN:
+ mv.visitLdcInsn(readConst(readUnsignedShort(v + 1),
+ c));
+ v += 3;
+ break;
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.ITFMETH_INSN:
+ int cpIndex = items[readUnsignedShort(v + 1)];
+ String iowner = readClass(cpIndex, c);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+ if (opcode < Opcodes.INVOKEVIRTUAL) {
+ mv.visitFieldInsn(opcode, iowner, iname, idesc);
+ } else {
+ mv.visitMethodInsn(opcode, iowner, iname, idesc);
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ v += 5;
+ } else {
+ v += 3;
+ }
+ break;
+ case ClassWriter.TYPE_INSN:
+ mv.visitTypeInsn(opcode, readClass(v + 1, c));
+ v += 3;
+ break;
+ case ClassWriter.IINC_INSN:
+ mv.visitIincInsn(b[v + 1] & 0xFF, b[v + 2]);
+ v += 3;
+ break;
+ // case MANA_INSN:
+ default:
+ mv.visitMultiANewArrayInsn(readClass(v + 1, c),
+ b[v + 3] & 0xFF);
+ v += 4;
+ break;
+ }
+ }
+ l = labels[codeEnd - codeStart];
+ if (l != null) {
+ mv.visitLabel(l);
+ }
+ // visits the local variable tables
+ if (!skipDebug && varTable != 0) {
+ int[] typeTable = null;
+ if (varTypeTable != 0) {
+ k = readUnsignedShort(varTypeTable) * 3;
+ w = varTypeTable + 2;
+ typeTable = new int[k];
+ while (k > 0) {
+ typeTable[--k] = w + 6; // signature
+ typeTable[--k] = readUnsignedShort(w + 8); // index
+ typeTable[--k] = readUnsignedShort(w); // start
+ w += 10;
+ }
+ }
+ k = readUnsignedShort(varTable);
+ w = varTable + 2;
+ for (; k > 0; --k) {
+ int start = readUnsignedShort(w);
+ int length = readUnsignedShort(w + 2);
+ int index = readUnsignedShort(w + 8);
+ String vsignature = null;
+ if (typeTable != null) {
+ for (int a = 0; a < typeTable.length; a += 3) {
+ if (typeTable[a] == start
+ && typeTable[a + 1] == index)
+ {
+ vsignature = readUTF8(typeTable[a + 2], c);
+ break;
+ }
+ }
+ }
+ mv.visitLocalVariable(readUTF8(w + 4, c),
+ readUTF8(w + 6, c),
+ vsignature,
+ labels[start],
+ labels[start + length],
+ index);
+ w += 10;
+ }
+ }
+ // visits the other attributes
+ while (cattrs != null) {
+ attr = cattrs.next;
+ cattrs.next = null;
+ mv.visitAttribute(cattrs);
+ cattrs = attr;
+ }
+ // visits the max stack and max locals values
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
+
+ /**
+ * Reads parameter annotations and makes the given visitor visit them.
+ *
+ * @param v start offset in {@link #b b} of the annotations to be read.
+ * @param desc the method descriptor.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param visible <tt>true</tt> if the annotations to be read are visible
+ * at runtime.
+ * @param mv the visitor that must visit the annotations.
+ */
+ private void readParameterAnnotations(
+ int v,
+ final String desc,
+ final char[] buf,
+ final boolean visible,
+ final MethodVisitor mv)
+ {
+ int i;
+ int n = b[v++] & 0xFF;
+ // workaround for a bug in javac (javac compiler generates a parameter
+ // annotation array whose size is equal to the number of parameters in
+ // the Java source file, while it should generate an array whose size is
+ // equal to the number of parameters in the method descriptor - which
+ // includes the synthetic parameters added by the compiler). This work-
+ // around supposes that the synthetic parameters are the first ones.
+ int synthetics = Type.getArgumentTypes(desc).length - n;
+ AnnotationVisitor av;
+ for (i = 0; i < synthetics; ++i) {
+ // virtual annotation to detect synthetic parameters in MethodWriter
+ av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ for (; i < n + synthetics; ++i) {
+ int j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ av = mv.visitParameterAnnotation(i, readUTF8(v, buf), visible);
+ v = readAnnotationValues(v + 2, buf, true, av);
+ }
+ }
+ }
+
+ /**
+ * Reads the values of an annotation and makes the given visitor visit them.
+ *
+ * @param v the start offset in {@link #b b} of the values to be read
+ * (including the unsigned short that gives the number of values).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param named if the annotation values are named or not.
+ * @param av the visitor that must visit the values.
+ * @return the end offset of the annotation values.
+ */
+ private int readAnnotationValues(
+ int v,
+ final char[] buf,
+ final boolean named,
+ final AnnotationVisitor av)
+ {
+ int i = readUnsignedShort(v);
+ v += 2;
+ if (named) {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+ }
+ } else {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v, buf, null, av);
+ }
+ }
+ if (av != null) {
+ av.visitEnd();
+ }
+ return v;
+ }
+
+ /**
+ * Reads a value of an annotation and makes the given visitor visit it.
+ *
+ * @param v the start offset in {@link #b b} of the value to be read (<i>not
+ * including the value name constant pool index</i>).
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param name the name of the value to be read.
+ * @param av the visitor that must visit the value.
+ * @return the end offset of the annotation value.
+ */
+ private int readAnnotationValue(
+ int v,
+ final char[] buf,
+ final String name,
+ final AnnotationVisitor av)
+ {
+ int i;
+ if (av == null) {
+ switch (b[v] & 0xFF) {
+ case 'e': // enum_const_value
+ return v + 5;
+ case '@': // annotation_value
+ return readAnnotationValues(v + 3, buf, true, null);
+ case '[': // array_value
+ return readAnnotationValues(v + 1, buf, false, null);
+ default:
+ return v + 3;
+ }
+ }
+ switch (b[v++] & 0xFF) {
+ case 'I': // pointer to CONSTANT_Integer
+ case 'J': // pointer to CONSTANT_Long
+ case 'F': // pointer to CONSTANT_Float
+ case 'D': // pointer to CONSTANT_Double
+ av.visit(name, readConst(readUnsignedShort(v), buf));
+ v += 2;
+ break;
+ case 'B': // pointer to CONSTANT_Byte
+ av.visit(name,
+ new Byte((byte) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'Z': // pointer to CONSTANT_Boolean
+ av.visit(name, readInt(items[readUnsignedShort(v)]) == 0
+ ? Boolean.FALSE
+ : Boolean.TRUE);
+ v += 2;
+ break;
+ case 'S': // pointer to CONSTANT_Short
+ av.visit(name,
+ new Short((short) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 'C': // pointer to CONSTANT_Char
+ av.visit(name,
+ new Character((char) readInt(items[readUnsignedShort(v)])));
+ v += 2;
+ break;
+ case 's': // pointer to CONSTANT_Utf8
+ av.visit(name, readUTF8(v, buf));
+ v += 2;
+ break;
+ case 'e': // enum_const_value
+ av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+ v += 4;
+ break;
+ case 'c': // class_info
+ av.visit(name, Type.getType(readUTF8(v, buf)));
+ v += 2;
+ break;
+ case '@': // annotation_value
+ v = readAnnotationValues(v + 2,
+ buf,
+ true,
+ av.visitAnnotation(name, readUTF8(v, buf)));
+ break;
+ case '[': // array_value
+ int size = readUnsignedShort(v);
+ v += 2;
+ if (size == 0) {
+ return readAnnotationValues(v - 2,
+ buf,
+ false,
+ av.visitArray(name));
+ }
+ switch (this.b[v++] & 0xFF) {
+ case 'B':
+ byte[] bv = new byte[size];
+ for (i = 0; i < size; i++) {
+ bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, bv);
+ --v;
+ break;
+ case 'Z':
+ boolean[] zv = new boolean[size];
+ for (i = 0; i < size; i++) {
+ zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+ v += 3;
+ }
+ av.visit(name, zv);
+ --v;
+ break;
+ case 'S':
+ short[] sv = new short[size];
+ for (i = 0; i < size; i++) {
+ sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, sv);
+ --v;
+ break;
+ case 'C':
+ char[] cv = new char[size];
+ for (i = 0; i < size; i++) {
+ cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, cv);
+ --v;
+ break;
+ case 'I':
+ int[] iv = new int[size];
+ for (i = 0; i < size; i++) {
+ iv[i] = readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, iv);
+ --v;
+ break;
+ case 'J':
+ long[] lv = new long[size];
+ for (i = 0; i < size; i++) {
+ lv[i] = readLong(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, lv);
+ --v;
+ break;
+ case 'F':
+ float[] fv = new float[size];
+ for (i = 0; i < size; i++) {
+ fv[i] = Float.intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, fv);
+ --v;
+ break;
+ case 'D':
+ double[] dv = new double[size];
+ for (i = 0; i < size; i++) {
+ dv[i] = Double.longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, dv);
+ --v;
+ break;
+ default:
+ v = readAnnotationValues(v - 3,
+ buf,
+ false,
+ av.visitArray(name));
+ }
+ }
+ return v;
+ }
+
+ private int readFrameType(
+ final Object[] frame,
+ final int index,
+ int v,
+ final char[] buf,
+ final Label[] labels)
+ {
+ int type = b[v++] & 0xFF;
+ switch (type) {
+ case 0:
+ frame[index] = Opcodes.TOP;
+ break;
+ case 1:
+ frame[index] = Opcodes.INTEGER;
+ break;
+ case 2:
+ frame[index] = Opcodes.FLOAT;
+ break;
+ case 3:
+ frame[index] = Opcodes.DOUBLE;
+ break;
+ case 4:
+ frame[index] = Opcodes.LONG;
+ break;
+ case 5:
+ frame[index] = Opcodes.NULL;
+ break;
+ case 6:
+ frame[index] = Opcodes.UNINITIALIZED_THIS;
+ break;
+ case 7: // Object
+ frame[index] = readClass(v, buf);
+ v += 2;
+ break;
+ default: // Uninitialized
+ frame[index] = readLabel(readUnsignedShort(v), labels);
+ v += 2;
+ }
+ return v;
+ }
+
+ /**
+ * Returns the label corresponding to the given offset. The default
+ * implementation of this method creates a label for the given offset if it
+ * has not been already created.
+ *
+ * @param offset a bytecode offset in a method.
+ * @param labels the already created labels, indexed by their offset. If a
+ * label already exists for offset this method must not create a new
+ * one. Otherwise it must store the new label in this array.
+ * @return a non null Label, which must be equal to labels[offset].
+ */
+ protected Label readLabel(int offset, Label[] labels) {
+ if (labels[offset] == null) {
+ labels[offset] = new Label();
+ }
+ return labels[offset];
+ }
+
+ /**
+ * Reads an attribute in {@link #b b}.
+ *
+ * @param attrs prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to the
+ * type of one the prototypes is ignored (i.e. an empty
+ * {@link Attribute} instance is returned).
+ * @param type the type of the attribute.
+ * @param off index of the first byte of the attribute's content in
+ * {@link #b b}. The 6 attribute header bytes, containing the type
+ * and the length of the attribute, are not taken into account here
+ * (they have already been read).
+ * @param len the length of the attribute's content.
+ * @param buf buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or
+ * {@link #readConst readConst}.
+ * @param codeOff index of the first byte of code's attribute content in
+ * {@link #b b}, or -1 if the attribute to be read is not a code
+ * attribute. The 6 attribute header bytes, containing the type and
+ * the length of the attribute, are not taken into account here.
+ * @param labels the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return the attribute that has been read, or <tt>null</tt> to skip this
+ * attribute.
+ */
+ private Attribute readAttribute(
+ final Attribute[] attrs,
+ final String type,
+ final int off,
+ final int len,
+ final char[] buf,
+ final int codeOff,
+ final Label[] labels)
+ {
+ for (int i = 0; i < attrs.length; ++i) {
+ if (attrs[i].type.equals(type)) {
+ return attrs[i].read(this, off, len, buf, codeOff, labels);
+ }
+ }
+ return new Attribute(type).read(this, off, len, null, -1, null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: low level parsing
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the start index of the constant pool item in {@link #b b}, plus
+ * one. <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param item the index a constant pool item.
+ * @return the start index of the constant pool item in {@link #b b}, plus
+ * one.
+ */
+ public int getItem(final int item) {
+ return items[item];
+ }
+
+ /**
+ * Reads a byte value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readByte(final int index) {
+ return b[index] & 0xFF;
+ }
+
+ /**
+ * Reads an unsigned short value in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readUnsignedShort(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public short readShort(final int index) {
+ byte[] b = this.b;
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readInt(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Reads a signed long value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public long readLong(final int index) {
+ long l1 = readInt(index);
+ long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+ return (l1 << 32) | l0;
+ }
+
+ /**
+ * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+ * is intended for {@link Attribute} sub classes, and is normally not needed
+ * by class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of an UTF8 constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 item.
+ */
+ public String readUTF8(int index, final char[] buf) {
+ int item = readUnsignedShort(index);
+ String s = strings[item];
+ if (s != null) {
+ return s;
+ }
+ index = items[item];
+ return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+ }
+
+ /**
+ * Reads UTF8 string in {@link #b b}.
+ *
+ * @param index start offset of the UTF8 string to be read.
+ * @param utfLen length of the UTF8 string to be read.
+ * @param buf buffer to be used to read the string. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 string.
+ */
+ private String readUTF(int index, final int utfLen, final char[] buf) {
+ int endIndex = index + utfLen;
+ byte[] b = this.b;
+ int strLen = 0;
+ int c, d, e;
+ while (index < endIndex) {
+ c = b[index++] & 0xFF;
+ switch (c >> 4) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ // 0xxxxxxx
+ buf[strLen++] = (char) c;
+ break;
+ case 12:
+ case 13:
+ // 110x xxxx 10xx xxxx
+ d = b[index++];
+ buf[strLen++] = (char) (((c & 0x1F) << 6) | (d & 0x3F));
+ break;
+ default:
+ // 1110 xxxx 10xx xxxx 10xx xxxx
+ d = b[index++];
+ e = b[index++];
+ buf[strLen++] = (char) (((c & 0x0F) << 12)
+ | ((d & 0x3F) << 6) | (e & 0x3F));
+ break;
+ }
+ }
+ return new String(buf, 0, strLen);
+ }
+
+ /**
+ * Reads a class constant pool item in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a class constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified class item.
+ */
+ public String readClass(final int index, final char[] buf) {
+ // computes the start index of the CONSTANT_Class item in b
+ // and reads the CONSTANT_Utf8 item designated by
+ // the first two bytes of this CONSTANT_Class item
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
+ * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param item the index of a constant pool item.
+ * @param buf buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String} or {@link Type} corresponding to
+ * the given constant pool item.
+ */
+ public Object readConst(final int item, final char[] buf) {
+ int index = items[item];
+ switch (b[index - 1]) {
+ case ClassWriter.INT:
+ return new Integer(readInt(index));
+ case ClassWriter.FLOAT:
+ return new Float(Float.intBitsToFloat(readInt(index)));
+ case ClassWriter.LONG:
+ return new Long(readLong(index));
+ case ClassWriter.DOUBLE:
+ return new Double(Double.longBitsToDouble(readLong(index)));
+ case ClassWriter.CLASS:
+ return Type.getObjectType(readUTF8(index, buf));
+ // case ClassWriter.STR:
+ default:
+ return readUTF8(index, buf);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassVisitor.java
new file mode 100644
index 0000000..b3234ad
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassVisitor.java
@@ -0,0 +1,196 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this interface must be called
+ * in the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* (<tt>visitInnerClass</tt> |
+ * <tt>visitField</tt> | <tt>visitMethod</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public interface ClassVisitor {
+
+ /**
+ * Visits the header of the class.
+ *
+ * @param version the class version.
+ * @param access the class's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the class is deprecated.
+ * @param name the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param signature the signature of this class. May be <tt>null</tt> if
+ * the class is not a generic one, and does not extend or implement
+ * generic classes or interfaces.
+ * @param superName the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces,
+ * the super class is {@link Object}. May be <tt>null</tt>, but
+ * only for the {@link Object} class.
+ * @param interfaces the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ void visit(
+ int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces);
+
+ /**
+ * Visits the source of the class.
+ *
+ * @param source the name of the source file from which the class was
+ * compiled. May be <tt>null</tt>.
+ * @param debug additional debug information to compute the correspondance
+ * between source and compiled elements of the class. May be
+ * <tt>null</tt>.
+ */
+ void visitSource(String source, String debug);
+
+ /**
+ * Visits the enclosing class of the class. This method must be called only
+ * if the class has an enclosing class.
+ *
+ * @param owner internal name of the enclosing class of the class.
+ * @param name the name of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ * @param desc the descriptor of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ */
+ void visitOuterClass(String owner, String name, String desc);
+
+ /**
+ * Visits an annotation of the class.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ AnnotationVisitor visitAnnotation(String desc, boolean visible);
+
+ /**
+ * Visits a non standard attribute of the class.
+ *
+ * @param attr an attribute.
+ */
+ void visitAttribute(Attribute attr);
+
+ /**
+ * Visits information about an inner class. This inner class is not
+ * necessarily a member of the class being visited.
+ *
+ * @param name the internal name of an inner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param outerName the internal name of the class to which the inner class
+ * belongs (see {@link Type#getInternalName() getInternalName}). May
+ * be <tt>null</tt> for not member classes.
+ * @param innerName the (simple) name of the inner class inside its
+ * enclosing class. May be <tt>null</tt> for anonymous inner
+ * classes.
+ * @param access the access flags of the inner class as originally declared
+ * in the enclosing class.
+ */
+ void visitInnerClass(
+ String name,
+ String outerName,
+ String innerName,
+ int access);
+
+ /**
+ * Visits a field of the class.
+ *
+ * @param access the field's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the field is synthetic and/or
+ * deprecated.
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type Type}).
+ * @param signature the field's signature. May be <tt>null</tt> if the
+ * field's type does not use generic types.
+ * @param value the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value, must
+ * be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String} (for <tt>int</tt>,
+ * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+ * respectively). <i>This parameter is only used for static fields</i>.
+ * Its value is ignored for non static fields, which must be
+ * initialized through bytecode instructions in constructors or
+ * methods.
+ * @return a visitor to visit field annotations and attributes, or
+ * <tt>null</tt> if this class visitor is not interested in
+ * visiting these annotations and attributes.
+ */
+ FieldVisitor visitField(
+ int access,
+ String name,
+ String desc,
+ String signature,
+ Object value);
+
+ /**
+ * Visits a method of the class. This method <i>must</i> return a new
+ * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is
+ * called, i.e., it should not return a previously returned visitor.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ * @param signature the method's signature. May be <tt>null</tt> if the
+ * method parameters, return type and exceptions do not use generic
+ * types.
+ * @param exceptions the internal names of the method's exception classes
+ * (see {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @return an object to visit the byte code of the method, or <tt>null</tt>
+ * if this class visitor is not interested in visiting the code of
+ * this method.
+ */
+ MethodVisitor visitMethod(
+ int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions);
+
+ /**
+ * Visits the end of the class. This method, which is the last one to be
+ * called, is used to inform the visitor that all the fields and methods of
+ * the class have been visited.
+ */
+ void visitEnd();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassWriter.java
new file mode 100644
index 0000000..ee15b99
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/ClassWriter.java
@@ -0,0 +1,1311 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassWriter implements ClassVisitor {
+
+ /**
+ * Flag to automatically compute the maximum stack size and the maximum
+ * number of local variables of methods. If this flag is set, then the
+ * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
+ * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
+ * method will be ignored, and computed automatically from the signature and
+ * the bytecode of each method.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_MAXS = 1;
+
+ /**
+ * Flag to automatically compute the stack map frames of methods from
+ * scratch. If this flag is set, then the calls to the
+ * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
+ * frames are recomputed from the methods bytecode. The arguments of the
+ * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+ * recomputed from the bytecode. In other words, computeFrames implies
+ * computeMaxs.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_FRAMES = 2;
+
+ /**
+ * The type of instructions without any argument.
+ */
+ static final int NOARG_INSN = 0;
+
+ /**
+ * The type of instructions with an signed byte argument.
+ */
+ static final int SBYTE_INSN = 1;
+
+ /**
+ * The type of instructions with an signed short argument.
+ */
+ static final int SHORT_INSN = 2;
+
+ /**
+ * The type of instructions with a local variable index argument.
+ */
+ static final int VAR_INSN = 3;
+
+ /**
+ * The type of instructions with an implicit local variable index argument.
+ */
+ static final int IMPLVAR_INSN = 4;
+
+ /**
+ * The type of instructions with a type descriptor argument.
+ */
+ static final int TYPE_INSN = 5;
+
+ /**
+ * The type of field and method invocations instructions.
+ */
+ static final int FIELDORMETH_INSN = 6;
+
+ /**
+ * The type of the INVOKEINTERFACE instruction.
+ */
+ static final int ITFMETH_INSN = 7;
+
+ /**
+ * The type of instructions with a 2 bytes bytecode offset label.
+ */
+ static final int LABEL_INSN = 8;
+
+ /**
+ * The type of instructions with a 4 bytes bytecode offset label.
+ */
+ static final int LABELW_INSN = 9;
+
+ /**
+ * The type of the LDC instruction.
+ */
+ static final int LDC_INSN = 10;
+
+ /**
+ * The type of the LDC_W and LDC2_W instructions.
+ */
+ static final int LDCW_INSN = 11;
+
+ /**
+ * The type of the IINC instruction.
+ */
+ static final int IINC_INSN = 12;
+
+ /**
+ * The type of the TABLESWITCH instruction.
+ */
+ static final int TABL_INSN = 13;
+
+ /**
+ * The type of the LOOKUPSWITCH instruction.
+ */
+ static final int LOOK_INSN = 14;
+
+ /**
+ * The type of the MULTIANEWARRAY instruction.
+ */
+ static final int MANA_INSN = 15;
+
+ /**
+ * The type of the WIDE instruction.
+ */
+ static final int WIDE_INSN = 16;
+
+ /**
+ * The instruction types of all JVM opcodes.
+ */
+ static final byte[] TYPE;
+
+ /**
+ * The type of CONSTANT_Class constant pool items.
+ */
+ static final int CLASS = 7;
+
+ /**
+ * The type of CONSTANT_Fieldref constant pool items.
+ */
+ static final int FIELD = 9;
+
+ /**
+ * The type of CONSTANT_Methodref constant pool items.
+ */
+ static final int METH = 10;
+
+ /**
+ * The type of CONSTANT_InterfaceMethodref constant pool items.
+ */
+ static final int IMETH = 11;
+
+ /**
+ * The type of CONSTANT_String constant pool items.
+ */
+ static final int STR = 8;
+
+ /**
+ * The type of CONSTANT_Integer constant pool items.
+ */
+ static final int INT = 3;
+
+ /**
+ * The type of CONSTANT_Float constant pool items.
+ */
+ static final int FLOAT = 4;
+
+ /**
+ * The type of CONSTANT_Long constant pool items.
+ */
+ static final int LONG = 5;
+
+ /**
+ * The type of CONSTANT_Double constant pool items.
+ */
+ static final int DOUBLE = 6;
+
+ /**
+ * The type of CONSTANT_NameAndType constant pool items.
+ */
+ static final int NAME_TYPE = 12;
+
+ /**
+ * The type of CONSTANT_Utf8 constant pool items.
+ */
+ static final int UTF8 = 1;
+
+ /**
+ * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_NORMAL = 13;
+
+ /**
+ * Uninitialized type Item stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table.
+ */
+ static final int TYPE_UNINIT = 14;
+
+ /**
+ * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_MERGED = 15;
+
+ /**
+ * Computes the instruction types of JVM opcodes.
+ */
+ static {
+ int i;
+ byte[] b = new byte[220];
+ String s = "AAAAAAAAAAAAAAAABCKLLDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ + "AAAAAAAAAAAAAAAAAMAAAAAAAAAAAAAAAAAAAAIIIIIIIIIIIIIIIIDNOAA"
+ + "AAAAGGGGGGGHAFBFAAFFAAQPIIJJIIIIIIIIIIIIIIIIII";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = (byte) (s.charAt(i) - 'A');
+ }
+ TYPE = b;
+
+ // code to generate the above string
+ //
+ // // SBYTE_INSN instructions
+ // b[Constants.NEWARRAY] = SBYTE_INSN;
+ // b[Constants.BIPUSH] = SBYTE_INSN;
+ //
+ // // SHORT_INSN instructions
+ // b[Constants.SIPUSH] = SHORT_INSN;
+ //
+ // // (IMPL)VAR_INSN instructions
+ // b[Constants.RET] = VAR_INSN;
+ // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ //
+ // // TYPE_INSN instructions
+ // b[Constants.NEW] = TYPE_INSN;
+ // b[Constants.ANEWARRAY] = TYPE_INSN;
+ // b[Constants.CHECKCAST] = TYPE_INSN;
+ // b[Constants.INSTANCEOF] = TYPE_INSN;
+ //
+ // // (Set)FIELDORMETH_INSN instructions
+ // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+ // b[i] = FIELDORMETH_INSN;
+ // }
+ // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+ //
+ // // LABEL(W)_INSN instructions
+ // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ // b[Constants.IFNULL] = LABEL_INSN;
+ // b[Constants.IFNONNULL] = LABEL_INSN;
+ // b[200] = LABELW_INSN; // GOTO_W
+ // b[201] = LABELW_INSN; // JSR_W
+ // // temporary opcodes used internally by ASM - see Label and
+ // MethodWriter
+ // for (i = 202; i < 220; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ //
+ // // LDC(_W) instructions
+ // b[Constants.LDC] = LDC_INSN;
+ // b[19] = LDCW_INSN; // LDC_W
+ // b[20] = LDCW_INSN; // LDC2_W
+ //
+ // // special instructions
+ // b[Constants.IINC] = IINC_INSN;
+ // b[Constants.TABLESWITCH] = TABL_INSN;
+ // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+ // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+ // b[196] = WIDE_INSN; // WIDE
+ //
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('A' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ /**
+ * The constant pool of this class.
+ */
+ final ByteVector pool;
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key;
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key2;
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key3;
+ /**
+ * <tt>true</tt> if the maximum stack size and number of local variables
+ * must be automatically computed.
+ */
+ private final boolean computeMaxs;
+ /**
+ * <tt>true</tt> if the stack map frames must be recomputed from scratch.
+ */
+ private final boolean computeFrames;
+ /**
+ * The class reader from which this class writer was constructed, if any.
+ */
+ ClassReader cr;
+ /**
+ * Minor and major version numbers of the class to be generated.
+ */
+ int version;
+ /**
+ * Index of the next item to be added in the constant pool.
+ */
+ int index;
+ /**
+ * The constant pool's hash table data.
+ */
+ Item[] items;
+ /**
+ * The threshold of the constant pool's hash table.
+ */
+ int threshold;
+ /**
+ * A type table used to temporarily store internal names that will not
+ * necessarily be stored in the constant pool. This type table is used by
+ * the control flow and data flow analysis algorithm used to compute stack
+ * map frames from scratch. This array associates to each index <tt>i</tt>
+ * the Item whose index is <tt>i</tt>. All Item objects stored in this
+ * array are also stored in the {@link #items} hash table. These two arrays
+ * allow to retrieve an Item from its index or, conversely, to get the index
+ * of an Item from its value. Each Item stores an internal name in its
+ * {@link Item#strVal1} field.
+ */
+ Item[] typeTable;
+ /**
+ * The internal name of this class.
+ */
+ String thisName;
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#next} field. This field stores the first element of
+ * this list.
+ */
+ FieldWriter firstField;
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#next} field. This field stores the last element of
+ * this list.
+ */
+ FieldWriter lastField;
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#next} field. This field stores the first element of
+ * this list.
+ */
+ MethodWriter firstMethod;
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#next} field. This field stores the last element of
+ * this list.
+ */
+ MethodWriter lastMethod;
+ /**
+ * <tt>true</tt> if the stack map tables of this class are invalid. The
+ * {@link MethodWriter#resizeInstructions} method cannot transform existing
+ * stack map tables, and so produces potentially invalid classes when it is
+ * executed. In this case the class is reread and rewritten with the
+ * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
+ * stack map tables when this option is used).
+ */
+ boolean invalidFrames;
+ /**
+ * Number of elements in the {@link #typeTable} array.
+ */
+ private short typeCount;
+ /**
+ * The access flags of this class.
+ */
+ private int access;
+ /**
+ * The constant pool item that contains the internal name of this class.
+ */
+ private int name;
+ /**
+ * The constant pool item that contains the signature of this class.
+ */
+ private int signature;
+ /**
+ * The constant pool item that contains the internal name of the super class
+ * of this class.
+ */
+ private int superName;
+ /**
+ * Number of interfaces implemented or extended by this class or interface.
+ */
+ private int interfaceCount;
+ /**
+ * The interfaces implemented or extended by this class or interface. More
+ * precisely, this array contains the indexes of the constant pool items
+ * that contain the internal names of these interfaces.
+ */
+ private int[] interfaces;
+ /**
+ * The index of the constant pool item that contains the name of the source
+ * file from which this class was compiled.
+ */
+ private int sourceFile;
+ /**
+ * The SourceDebug attribute of this class.
+ */
+ private ByteVector sourceDebug;
+ /**
+ * The constant pool item that contains the name of the enclosing class of
+ * this class.
+ */
+ private int enclosingMethodOwner;
+ /**
+ * The constant pool item that contains the name and descriptor of the
+ * enclosing method of this class.
+ */
+ private int enclosingMethod;
+ /**
+ * The runtime visible annotations of this class.
+ */
+ private AnnotationWriter anns;
+ /**
+ * The runtime invisible annotations of this class.
+ */
+ private AnnotationWriter ianns;
+ /**
+ * The non standard attributes of this class.
+ */
+ private Attribute attrs;
+ /**
+ * The number of entries in the InnerClasses attribute.
+ */
+ private int innerClassesCount;
+
+ // ------------------------------------------------------------------------
+ // Static initializer
+ // ------------------------------------------------------------------------
+ /**
+ * The InnerClasses attribute.
+ */
+ private ByteVector innerClasses;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassWriter} object.
+ *
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final int flags) {
+ index = 1;
+ pool = new ByteVector();
+ items = new Item[256];
+ threshold = (int) (0.75d * items.length);
+ key = new Item();
+ key2 = new Item();
+ key3 = new Item();
+ this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
+ this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+ }
+
+ /**
+ * Constructs a new {@link ClassWriter} object and enables optimizations for
+ * "mostly add" bytecode transformations. These optimizations are the
+ * following:
+ *
+ * <ul> <li>The constant pool from the original class is copied as is in
+ * the new class, which saves time. New constant pool entries will be added
+ * at the end if necessary, but unused constant pool entries <i>won't be
+ * removed</i>.</li> <li>Methods that are not transformed are copied as
+ * is in the new class, directly from the original class bytecode (i.e.
+ * without emitting visit events for all the method instructions), which
+ * saves a <i>lot</i> of time. Untransformed methods are detected by the
+ * fact that the {@link ClassReader} receives {@link MethodVisitor} objects
+ * that come from a {@link ClassWriter} (and not from a custom
+ * {@link ClassAdapter} or any other {@link ClassVisitor} instance).</li>
+ * </ul>
+ *
+ * @param classReader the {@link ClassReader} used to read the original
+ * class. It will be used to copy the entire constant pool from the
+ * original class and also to copy other fragments of original
+ * bytecode where applicable.
+ * @param flags option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS}, {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final ClassReader classReader, final int flags) {
+ this(flags);
+ classReader.copyPool(this);
+ this.cr = classReader;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ this.version = version;
+ this.access = access;
+ this.name = newClass(name);
+ thisName = name;
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = newUTF8(signature);
+ }
+ this.superName = superName == null ? 0 : newClass(superName);
+ if (interfaces != null && interfaces.length > 0) {
+ interfaceCount = interfaces.length;
+ this.interfaces = new int[interfaceCount];
+ for (int i = 0; i < interfaceCount; ++i) {
+ this.interfaces[i] = newClass(interfaces[i]);
+ }
+ }
+ }
+
+ public void visitSource(final String file, final String debug) {
+ if (file != null) {
+ sourceFile = newUTF8(file);
+ }
+ if (debug != null) {
+ sourceDebug = new ByteVector().putUTF8(debug);
+ }
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ enclosingMethodOwner = newClass(owner);
+ if (name != null && desc != null) {
+ enclosingMethod = newNameType(name, desc);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ if (innerClasses == null) {
+ innerClasses = new ByteVector();
+ }
+ ++innerClassesCount;
+ innerClasses.putShort(name == null ? 0 : newClass(name));
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ return new FieldWriter(this, access, name, desc, signature, value);
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ return new MethodWriter(this,
+ access,
+ name,
+ desc,
+ signature,
+ exceptions,
+ computeMaxs,
+ computeFrames);
+ }
+
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Other public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the bytecode of the class that was build with this class writer.
+ *
+ * @return the bytecode of the class that was build with this class writer.
+ */
+ public byte[] toByteArray() {
+ // computes the real size of the bytecode of this class
+ int size = 24 + 2 * interfaceCount;
+ int nbFields = 0;
+ FieldWriter fb = firstField;
+ while (fb != null) {
+ ++nbFields;
+ size += fb.getSize();
+ fb = fb.next;
+ }
+ int nbMethods = 0;
+ MethodWriter mb = firstMethod;
+ while (mb != null) {
+ ++nbMethods;
+ size += mb.getSize();
+ mb = mb.next;
+ }
+ int attributeCount = 0;
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("Signature");
+ }
+ if (sourceFile != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("SourceFile");
+ }
+ if (sourceDebug != null) {
+ ++attributeCount;
+ size += sourceDebug.length + 4;
+ newUTF8("SourceDebugExtension");
+ }
+ if (enclosingMethodOwner != 0) {
+ ++attributeCount;
+ size += 10;
+ newUTF8("EnclosingMethod");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Deprecated");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (version & 0xffff) < Opcodes.V1_5)
+ {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Synthetic");
+ }
+ if (innerClasses != null) {
+ ++attributeCount;
+ size += 8 + innerClasses.length;
+ newUTF8("InnerClasses");
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ size += 8 + anns.getSize();
+ newUTF8("RuntimeVisibleAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ size += 8 + ianns.getSize();
+ newUTF8("RuntimeInvisibleAnnotations");
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ size += attrs.getSize(this, null, 0, -1, -1);
+ }
+ size += pool.length;
+ // allocates a byte vector of this size, in order to avoid unnecessary
+ // arraycopy operations in the ByteVector.enlarge() method
+ ByteVector out = new ByteVector(size);
+ out.putInt(0xCAFEBABE).putInt(version);
+ out.putShort(index).putByteArray(pool.data, 0, pool.length);
+ out.putShort(access).putShort(name).putShort(superName);
+ out.putShort(interfaceCount);
+ for (int i = 0; i < interfaceCount; ++i) {
+ out.putShort(interfaces[i]);
+ }
+ out.putShort(nbFields);
+ fb = firstField;
+ while (fb != null) {
+ fb.put(out);
+ fb = fb.next;
+ }
+ out.putShort(nbMethods);
+ mb = firstMethod;
+ while (mb != null) {
+ mb.put(out);
+ mb = mb.next;
+ }
+ out.putShort(attributeCount);
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
+ }
+ if (sourceFile != 0) {
+ out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
+ }
+ if (sourceDebug != null) {
+ int len = sourceDebug.length - 2;
+ out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
+ out.putByteArray(sourceDebug.data, 2, len);
+ }
+ if (enclosingMethodOwner != 0) {
+ out.putShort(newUTF8("EnclosingMethod")).putInt(4);
+ out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(newUTF8("Deprecated")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (version & 0xffff) < Opcodes.V1_5)
+ {
+ out.putShort(newUTF8("Synthetic")).putInt(0);
+ }
+ if (innerClasses != null) {
+ out.putShort(newUTF8("InnerClasses"));
+ out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
+ out.putByteArray(innerClasses.data, 0, innerClasses.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(this, null, 0, -1, -1, out);
+ }
+ if (invalidFrames) {
+ ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
+ new ClassReader(out.data).accept(cw, ClassReader.SKIP_FRAMES);
+ return cw.toByteArray();
+ }
+ return out.data;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: constant pool management
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ *
+ * @param cst the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double}, a {@link String} or a
+ * {@link Type}.
+ * @return a new or already existing constant item with the given value.
+ */
+ Item newConstItem(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Byte) {
+ int val = ((Byte) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Character) {
+ int val = ((Character) cst).charValue();
+ return newInteger(val);
+ } else if (cst instanceof Short) {
+ int val = ((Short) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Boolean) {
+ int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+ return newInteger(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ return newFloat(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ return newLong(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ return newDouble(val);
+ } else if (cst instanceof String) {
+ return newString((String) cst);
+ } else if (cst instanceof Type) {
+ Type t = (Type) cst;
+ return newClassItem(t.getSort() == Type.OBJECT
+ ? t.getInternalName()
+ : t.getDescriptor());
+ } else {
+ throw new IllegalArgumentException("value " + cst);
+ }
+ }
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param cst the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ * @return the index of a new or already existing constant item with the
+ * given value.
+ */
+ public int newConst(final Object cst) {
+ return newConstItem(cst).index;
+ }
+
+ /**
+ * Adds an UTF8 string to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param value the String value.
+ * @return the index of a new or already existing UTF8 item.
+ */
+ public int newUTF8(final String value) {
+ key.set(UTF8, value, null, null);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(UTF8).putUTF8(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value the internal name of the class.
+ * @return a new or already existing class reference item.
+ */
+ Item newClassItem(final String value) {
+ key2.set(CLASS, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(CLASS, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value the internal name of the class.
+ * @return the index of a new or already existing class reference item.
+ */
+ public int newClass(final String value) {
+ return newClassItem(value).index;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner the internal name of the field's owner class.
+ * @param name the field's name.
+ * @param desc the field's descriptor.
+ * @return a new or already existing field reference item.
+ */
+ Item newFieldItem(final String owner, final String name, final String desc)
+ {
+ key3.set(FIELD, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(FIELD, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner the internal name of the field's owner class.
+ * @param name the field's name.
+ * @param desc the field's descriptor.
+ * @return the index of a new or already existing field reference item.
+ */
+ public int newField(final String owner, final String name, final String desc)
+ {
+ return newFieldItem(owner, name, desc).index;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param desc the method's descriptor.
+ * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return a new or already existing method reference item.
+ */
+ Item newMethodItem(
+ final String owner,
+ final String name,
+ final String desc,
+ final boolean itf)
+ {
+ int type = itf ? IMETH : METH;
+ key3.set(type, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(type, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner the internal name of the method's owner class.
+ * @param name the method's name.
+ * @param desc the method's descriptor.
+ * @param itf <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return the index of a new or already existing method reference item.
+ */
+ public int newMethod(
+ final String owner,
+ final String name,
+ final String desc,
+ final boolean itf)
+ {
+ return newMethodItem(owner, name, desc, itf).index;
+ }
+
+ /**
+ * Adds an integer to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param value the int value.
+ * @return a new or already existing int item.
+ */
+ Item newInteger(final int value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(INT).putInt(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a float to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the float value.
+ * @return a new or already existing float item.
+ */
+ Item newFloat(final float value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(FLOAT).putInt(key.intVal);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a long to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the long value.
+ * @return a new or already existing long item.
+ */
+ Item newLong(final long value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(LONG).putLong(value);
+ result = new Item(index, key);
+ put(result);
+ index += 2;
+ }
+ return result;
+ }
+
+ /**
+ * Adds a double to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the double value.
+ * @return a new or already existing double item.
+ */
+ Item newDouble(final double value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(DOUBLE).putLong(key.longVal);
+ result = new Item(index, key);
+ put(result);
+ index += 2;
+ }
+ return result;
+ }
+
+ /**
+ * Adds a string to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value the String value.
+ * @return a new or already existing string item.
+ */
+ private Item newString(final String value) {
+ key2.set(STR, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(STR, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a name and type to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param name a name.
+ * @param desc a type descriptor.
+ * @return the index of a new or already existing name and type item.
+ */
+ public int newNameType(final String name, final String desc) {
+ key2.set(NAME_TYPE, name, desc, null);
+ Item result = get(key2);
+ if (result == null) {
+ put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given internal name to {@link #typeTable} and returns its index.
+ * Does nothing if the type table already contains this internal name.
+ *
+ * @param type the internal name to be added to the type table.
+ * @return the index of this internal name in the type table.
+ */
+ int addType(final String type) {
+ key.set(TYPE_NORMAL, type, null, null);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given "uninitialized" type to {@link #typeTable} and returns its
+ * index. This method is used for UNINITIALIZED types, made of an internal
+ * name and a bytecode offset.
+ *
+ * @param type the internal name to be added to the type table.
+ * @param offset the bytecode offset of the NEW instruction that created
+ * this UNINITIALIZED type value.
+ * @return the index of this internal name in the type table.
+ */
+ int addUninitializedType(final String type, final int offset) {
+ key.type = TYPE_UNINIT;
+ key.intVal = offset;
+ key.strVal1 = type;
+ key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given Item to {@link #typeTable}.
+ *
+ * @param item the value to be added to the type table.
+ * @return the added Item, which a new Item instance with the same value as
+ * the given Item.
+ */
+ private Item addType(final Item item) {
+ ++typeCount;
+ Item result = new Item(typeCount, key);
+ put(result);
+ if (typeTable == null) {
+ typeTable = new Item[16];
+ }
+ if (typeCount == typeTable.length) {
+ Item[] newTable = new Item[2 * typeTable.length];
+ System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
+ typeTable = newTable;
+ }
+ typeTable[typeCount] = result;
+ return result;
+ }
+
+ /**
+ * Returns the index of the common super type of the two given types. This
+ * method calls {@link #getCommonSuperClass} and caches the result in the
+ * {@link #items} hash table to speedup future calls with the same
+ * parameters.
+ *
+ * @param type1 index of an internal name in {@link #typeTable}.
+ * @param type2 index of an internal name in {@link #typeTable}.
+ * @return the index of the common super type of the two given types.
+ */
+ int getMergedType(final int type1, final int type2) {
+ key2.type = TYPE_MERGED;
+ key2.longVal = type1 | (((long) type2) << 32);
+ key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
+ Item result = get(key2);
+ if (result == null) {
+ String t = typeTable[type1].strVal1;
+ String u = typeTable[type2].strVal1;
+ key2.intVal = addType(getCommonSuperClass(t, u));
+ result = new Item((short) 0, key2);
+ put(result);
+ }
+ return result.intVal;
+ }
+
+ /**
+ * Returns the common super type of the two given types. The default
+ * implementation of this method <i>loads<i> the two given classes and uses
+ * the java.lang.Class methods to find the common super class. It can be
+ * overridden to compute this common super type in other ways, in particular
+ * without actually loading any class, or to take into account the class
+ * that is currently being generated by this ClassWriter, which can of
+ * course not be loaded since it is under construction.
+ *
+ * @param type1 the internal name of a class.
+ * @param type2 the internal name of another class.
+ * @return the internal name of the common super class of the two given
+ * classes.
+ */
+ protected String getCommonSuperClass(final String type1, final String type2)
+ {
+ Class c, d;
+ try {
+ c = Class.forName(type1.replace('/', '.'));
+ d = Class.forName(type2.replace('/', '.'));
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ if (c.isAssignableFrom(d)) {
+ return type1;
+ }
+ if (d.isAssignableFrom(c)) {
+ return type2;
+ }
+ if (c.isInterface() || d.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ c = c.getSuperclass();
+ } while (!c.isAssignableFrom(d));
+ return c.getName().replace('.', '/');
+ }
+ }
+
+ /**
+ * Returns the constant pool's hash table item which is equal to the given
+ * item.
+ *
+ * @param key a constant pool item.
+ * @return the constant pool's hash table item which is equal to the given
+ * item, or <tt>null</tt> if there is no such item.
+ */
+ private Item get(final Item key) {
+ Item i = items[key.hashCode % items.length];
+ while (i != null && !key.isEqualTo(i)) {
+ i = i.next;
+ }
+ return i;
+ }
+
+ /**
+ * Puts the given item in the constant pool's hash table. The hash table
+ * <i>must</i> not already contains this item.
+ *
+ * @param i the item to be added to the constant pool's hash table.
+ */
+ private void put(final Item i) {
+ if (index > threshold) {
+ int ll = items.length;
+ int nl = ll * 2 + 1;
+ Item[] newItems = new Item[nl];
+ for (int l = ll - 1; l >= 0; --l) {
+ Item j = items[l];
+ while (j != null) {
+ int index = j.hashCode % newItems.length;
+ Item k = j.next;
+ j.next = newItems[index];
+ newItems[index] = j;
+ j = k;
+ }
+ }
+ items = newItems;
+ threshold = (int) (nl * 0.75);
+ }
+ int index = i.hashCode % items.length;
+ i.next = items[index];
+ items[index] = i;
+ }
+
+ /**
+ * Puts one byte and two shorts into the constant pool.
+ *
+ * @param b a byte.
+ * @param s1 a short.
+ * @param s2 another short.
+ */
+ private void put122(final int b, final int s1, final int s2) {
+ pool.put12(b, s1).putShort(s2);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Edge.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Edge.java
new file mode 100644
index 0000000..cd4d041
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Edge.java
@@ -0,0 +1,75 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ *
+ * @author Eric Bruneton
+ */
+class Edge {
+
+ /**
+ * Denotes a normal control flow graph edge.
+ */
+ static final int NORMAL = 0;
+
+ /**
+ * Denotes a control flow graph edge corresponding to an exception handler.
+ * More precisely any {@link Edge} whose {@link #info} is strictly positive
+ * corresponds to an exception handler. The actual value of {@link #info} is
+ * the index, in the {@link ClassWriter} type table, of the exception that
+ * is catched.
+ */
+ static final int EXCEPTION = 0x7FFFFFFF;
+
+ /**
+ * Information about this control flow graph edge. If
+ * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
+ * stack size in the basic block from which this edge originates. This size
+ * is equal to the stack size at the "jump" instruction to which this edge
+ * corresponds, relatively to the stack size at the beginning of the
+ * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
+ * this field is the kind of this control flow graph edge (i.e. NORMAL or
+ * EXCEPTION).
+ */
+ int info;
+
+ /**
+ * The successor block of the basic block from which this edge originates.
+ */
+ Label successor;
+
+ /**
+ * The next edge in the list of successors of the originating basic block.
+ * See {@link Label#successors successors}.
+ */
+ Edge next;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldVisitor.java
new file mode 100644
index 0000000..f322693
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldVisitor.java
@@ -0,0 +1,64 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this interface must be called
+ * in the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public interface FieldVisitor {
+
+ /**
+ * Visits an annotation of the field.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ AnnotationVisitor visitAnnotation(String desc, boolean visible);
+
+ /**
+ * Visits a non standard attribute of the field.
+ *
+ * @param attr an attribute.
+ */
+ void visitAttribute(Attribute attr);
+
+ /**
+ * Visits the end of the field. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the field have been visited.
+ */
+ void visitEnd();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldWriter.java
new file mode 100644
index 0000000..6753950
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/FieldWriter.java
@@ -0,0 +1,264 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ *
+ * @author Eric Bruneton
+ */
+final class FieldWriter implements FieldVisitor {
+
+ /**
+ * The class writer to which this field must be added.
+ */
+ private final ClassWriter cw;
+ /**
+ * Access flags of this field.
+ */
+ private final int access;
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * field.
+ */
+ private final int desc;
+ /**
+ * Next field writer (see {@link ClassWriter#firstField firstField}).
+ */
+ FieldWriter next;
+ /**
+ * The index of the constant pool item that contains the signature of this
+ * field.
+ */
+ private int signature;
+
+ /**
+ * The index of the constant pool item that contains the constant value of
+ * this field.
+ */
+ private int value;
+
+ /**
+ * The runtime visible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The non standard attributes of this field. May be <tt>null</tt>.
+ */
+ private Attribute attrs;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link FieldWriter}.
+ *
+ * @param cw the class writer to which this field must be added.
+ * @param access the field's access flags (see {@link Opcodes}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type}).
+ * @param signature the field's signature. May be <tt>null</tt>.
+ * @param value the field's constant value. May be <tt>null</tt>.
+ */
+ FieldWriter(
+ final ClassWriter cw,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ if (cw.firstField == null) {
+ cw.firstField = this;
+ } else {
+ cw.lastField.next = this;
+ }
+ cw.lastField = this;
+ this.cw = cw;
+ this.access = access;
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = cw.newUTF8(signature);
+ }
+ if (value != null) {
+ this.value = cw.newConstItem(value).index;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the FieldVisitor interface
+ // ------------------------------------------------------------------------
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of this field.
+ *
+ * @return the size of this field.
+ */
+ int getSize() {
+ int size = 8;
+ if (value != 0) {
+ cw.newUTF8("ConstantValue");
+ size += 8;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ cw.newUTF8("Signature");
+ size += 8;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the content of this field into the given byte vector.
+ *
+ * @param out where the content of this field must be put.
+ */
+ void put(final ByteVector out) {
+ out.putShort(access).putShort(name).putShort(desc);
+ int attributeCount = 0;
+ if (value != 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (value != 0) {
+ out.putShort(cw.newUTF8("ConstantValue"));
+ out.putInt(2).putShort(value);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(cw.newUTF8("Signature"));
+ out.putInt(2).putShort(signature);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Frame.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Frame.java
new file mode 100644
index 0000000..4f39494
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Frame.java
@@ -0,0 +1,1388 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * Information about the input and output stack map frames of a basic block.
+ *
+ * @author Eric Bruneton
+ */
+final class Frame {
+
+ /*
+ * Frames are computed in a two steps process: during the visit of each
+ * instruction, the state of the frame at the end of current basic block is
+ * updated by simulating the action of the instruction on the previous state
+ * of this so called "output frame". In visitMaxs, a fix point algorithm is
+ * used to compute the "input frame" of each basic block, i.e. the stack map
+ * frame at the begining of the basic block, starting from the input frame
+ * of the first basic block (which is computed from the method descriptor),
+ * and by using the previously computed output frames to compute the input
+ * state of the other blocks.
+ *
+ * All output and input frames are stored as arrays of integers. Reference
+ * and array types are represented by an index into a type table (which is
+ * not the same as the constant pool of the class, in order to avoid adding
+ * unnecessary constants in the pool - not all computed frames will end up
+ * being stored in the stack map table). This allows very fast type
+ * comparisons.
+ *
+ * Output stack map frames are computed relatively to the input frame of the
+ * basic block, which is not yet known when output frames are computed. It
+ * is therefore necessary to be able to represent abstract types such as
+ * "the type at position x in the input frame locals" or "the type at
+ * position x from the top of the input frame stack" or even "the type at
+ * position x in the input frame, with y more (or less) array dimensions".
+ * This explains the rather complicated type format used in output frames.
+ *
+ * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
+ * signed number of array dimensions (from -8 to 7). KIND is either BASE,
+ * LOCAL or STACK. BASE is used for types that are not relative to the input
+ * frame. LOCAL is used for types that are relative to the input local
+ * variable types. STACK is used for types that are relative to the input
+ * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
+ * the input local variable types. For STACK types, it is a position
+ * relatively to the top of input frame stack. For BASE types, it is either
+ * one of the constants defined in FrameVisitor, or for OBJECT and
+ * UNINITIALIZED types, a tag and an index in the type table.
+ *
+ * Output frames can contain types of any kind and with a positive or
+ * negative dimension (and even unassigned types, represented by 0 - which
+ * does not correspond to any valid type value). Input frames can only
+ * contain BASE types of positive or null dimension. In all cases the type
+ * table contains only internal type names (array type descriptors are
+ * forbidden - dimensions must be represented through the DIM field).
+ *
+ * The LONG and DOUBLE types are always represented by using two slots (LONG +
+ * TOP or DOUBLE + TOP), for local variable types as well as in the operand
+ * stack. This is necessary to be able to simulate DUPx_y instructions,
+ * whose effect would be dependent on the actual type values if types were
+ * always represented by a single slot in the stack (and this is not
+ * possible, since actual type values are not always known - cf LOCAL and
+ * STACK type kinds).
+ */
+
+ /**
+ * Mask to get the dimension of a frame type. This dimension is a signed
+ * integer between -8 and 7.
+ */
+ static final int DIM = 0xF0000000;
+
+ /**
+ * Constant to be added to a type to get a type with one more dimension.
+ */
+ static final int ARRAY_OF = 0x10000000;
+
+ /**
+ * Constant to be added to a type to get a type with one less dimension.
+ */
+ static final int ELEMENT_OF = 0xF0000000;
+
+ /**
+ * Mask to get the kind of a frame type.
+ *
+ * @see #BASE
+ * @see #LOCAL
+ * @see #STACK
+ */
+ static final int KIND = 0xF000000;
+
+ /**
+ * Mask to get the value of a frame type.
+ */
+ static final int VALUE = 0xFFFFFF;
+
+ /**
+ * Mask to get the kind of base types.
+ */
+ static final int BASE_KIND = 0xFF00000;
+
+ /**
+ * Mask to get the value of base types.
+ */
+ static final int BASE_VALUE = 0xFFFFF;
+
+ /**
+ * Kind of the types that are not relative to an input stack map frame.
+ */
+ static final int BASE = 0x1000000;
+
+ /**
+ * Base kind of the base reference types. The BASE_VALUE of such types is an
+ * index into the type table.
+ */
+ static final int OBJECT = BASE | 0x700000;
+
+ /**
+ * Base kind of the uninitialized base types. The BASE_VALUE of such types
+ * in an index into the type table (the Item at that index contains both an
+ * instruction offset and an internal class name).
+ */
+ static final int UNINITIALIZED = BASE | 0x800000;
+ /**
+ * The TOP type. This is a BASE type.
+ */
+ static final int TOP = BASE | 0;
+ /**
+ * The BOOLEAN type. This is a BASE type mainly used for array types.
+ */
+ static final int BOOLEAN = BASE | 9;
+ /**
+ * The BYTE type. This is a BASE type mainly used for array types.
+ */
+ static final int BYTE = BASE | 10;
+ /**
+ * The CHAR type. This is a BASE type mainly used for array types.
+ */
+ static final int CHAR = BASE | 11;
+ /**
+ * The SHORT type. This is a BASE type mainly used for array types.
+ */
+ static final int SHORT = BASE | 12;
+ /**
+ * The INTEGER type. This is a BASE type.
+ */
+ static final int INTEGER = BASE | 1;
+ /**
+ * The FLOAT type. This is a BASE type.
+ */
+ static final int FLOAT = BASE | 2;
+ /**
+ * The DOUBLE type. This is a BASE type.
+ */
+ static final int DOUBLE = BASE | 3;
+ /**
+ * The LONG type. This is a BASE type.
+ */
+ static final int LONG = BASE | 4;
+ /**
+ * The NULL type. This is a BASE type.
+ */
+ static final int NULL = BASE | 5;
+ /**
+ * The UNINITIALIZED_THIS type. This is a BASE type.
+ */
+ static final int UNINITIALIZED_THIS = BASE | 6;
+ /**
+ * The stack size variation corresponding to each JVM instruction. This
+ * stack variation is equal to the size of the values produced by an
+ * instruction, minus the size of the values consumed by this instruction.
+ */
+ static final int[] SIZE;
+ /**
+ * Kind of the types that are relative to the local variable types of an
+ * input stack map frame. The value of such types is a local variable index.
+ */
+ private static final int LOCAL = 0x2000000;
+ /**
+ * Kind of the the types that are relative to the stack of an input stack
+ * map frame. The value of such types is a position relatively to the top of
+ * this stack.
+ */
+ private static final int STACK = 0x3000000;
+
+ /**
+ * Computes the stack size variation corresponding to each JVM instruction.
+ */
+ static {
+ int i;
+ int[] b = new int[202];
+ String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
+ + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
+ + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
+ + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = s.charAt(i) - 'E';
+ }
+ SIZE = b;
+
+ // code to generate the above string
+ //
+ // int NA = 0; // not applicable (unused opcode or variable size opcode)
+ //
+ // b = new int[] {
+ // 0, //NOP, // visitInsn
+ // 1, //ACONST_NULL, // -
+ // 1, //ICONST_M1, // -
+ // 1, //ICONST_0, // -
+ // 1, //ICONST_1, // -
+ // 1, //ICONST_2, // -
+ // 1, //ICONST_3, // -
+ // 1, //ICONST_4, // -
+ // 1, //ICONST_5, // -
+ // 2, //LCONST_0, // -
+ // 2, //LCONST_1, // -
+ // 1, //FCONST_0, // -
+ // 1, //FCONST_1, // -
+ // 1, //FCONST_2, // -
+ // 2, //DCONST_0, // -
+ // 2, //DCONST_1, // -
+ // 1, //BIPUSH, // visitIntInsn
+ // 1, //SIPUSH, // -
+ // 1, //LDC, // visitLdcInsn
+ // NA, //LDC_W, // -
+ // NA, //LDC2_W, // -
+ // 1, //ILOAD, // visitVarInsn
+ // 2, //LLOAD, // -
+ // 1, //FLOAD, // -
+ // 2, //DLOAD, // -
+ // 1, //ALOAD, // -
+ // NA, //ILOAD_0, // -
+ // NA, //ILOAD_1, // -
+ // NA, //ILOAD_2, // -
+ // NA, //ILOAD_3, // -
+ // NA, //LLOAD_0, // -
+ // NA, //LLOAD_1, // -
+ // NA, //LLOAD_2, // -
+ // NA, //LLOAD_3, // -
+ // NA, //FLOAD_0, // -
+ // NA, //FLOAD_1, // -
+ // NA, //FLOAD_2, // -
+ // NA, //FLOAD_3, // -
+ // NA, //DLOAD_0, // -
+ // NA, //DLOAD_1, // -
+ // NA, //DLOAD_2, // -
+ // NA, //DLOAD_3, // -
+ // NA, //ALOAD_0, // -
+ // NA, //ALOAD_1, // -
+ // NA, //ALOAD_2, // -
+ // NA, //ALOAD_3, // -
+ // -1, //IALOAD, // visitInsn
+ // 0, //LALOAD, // -
+ // -1, //FALOAD, // -
+ // 0, //DALOAD, // -
+ // -1, //AALOAD, // -
+ // -1, //BALOAD, // -
+ // -1, //CALOAD, // -
+ // -1, //SALOAD, // -
+ // -1, //ISTORE, // visitVarInsn
+ // -2, //LSTORE, // -
+ // -1, //FSTORE, // -
+ // -2, //DSTORE, // -
+ // -1, //ASTORE, // -
+ // NA, //ISTORE_0, // -
+ // NA, //ISTORE_1, // -
+ // NA, //ISTORE_2, // -
+ // NA, //ISTORE_3, // -
+ // NA, //LSTORE_0, // -
+ // NA, //LSTORE_1, // -
+ // NA, //LSTORE_2, // -
+ // NA, //LSTORE_3, // -
+ // NA, //FSTORE_0, // -
+ // NA, //FSTORE_1, // -
+ // NA, //FSTORE_2, // -
+ // NA, //FSTORE_3, // -
+ // NA, //DSTORE_0, // -
+ // NA, //DSTORE_1, // -
+ // NA, //DSTORE_2, // -
+ // NA, //DSTORE_3, // -
+ // NA, //ASTORE_0, // -
+ // NA, //ASTORE_1, // -
+ // NA, //ASTORE_2, // -
+ // NA, //ASTORE_3, // -
+ // -3, //IASTORE, // visitInsn
+ // -4, //LASTORE, // -
+ // -3, //FASTORE, // -
+ // -4, //DASTORE, // -
+ // -3, //AASTORE, // -
+ // -3, //BASTORE, // -
+ // -3, //CASTORE, // -
+ // -3, //SASTORE, // -
+ // -1, //POP, // -
+ // -2, //POP2, // -
+ // 1, //DUP, // -
+ // 1, //DUP_X1, // -
+ // 1, //DUP_X2, // -
+ // 2, //DUP2, // -
+ // 2, //DUP2_X1, // -
+ // 2, //DUP2_X2, // -
+ // 0, //SWAP, // -
+ // -1, //IADD, // -
+ // -2, //LADD, // -
+ // -1, //FADD, // -
+ // -2, //DADD, // -
+ // -1, //ISUB, // -
+ // -2, //LSUB, // -
+ // -1, //FSUB, // -
+ // -2, //DSUB, // -
+ // -1, //IMUL, // -
+ // -2, //LMUL, // -
+ // -1, //FMUL, // -
+ // -2, //DMUL, // -
+ // -1, //IDIV, // -
+ // -2, //LDIV, // -
+ // -1, //FDIV, // -
+ // -2, //DDIV, // -
+ // -1, //IREM, // -
+ // -2, //LREM, // -
+ // -1, //FREM, // -
+ // -2, //DREM, // -
+ // 0, //INEG, // -
+ // 0, //LNEG, // -
+ // 0, //FNEG, // -
+ // 0, //DNEG, // -
+ // -1, //ISHL, // -
+ // -1, //LSHL, // -
+ // -1, //ISHR, // -
+ // -1, //LSHR, // -
+ // -1, //IUSHR, // -
+ // -1, //LUSHR, // -
+ // -1, //IAND, // -
+ // -2, //LAND, // -
+ // -1, //IOR, // -
+ // -2, //LOR, // -
+ // -1, //IXOR, // -
+ // -2, //LXOR, // -
+ // 0, //IINC, // visitIincInsn
+ // 1, //I2L, // visitInsn
+ // 0, //I2F, // -
+ // 1, //I2D, // -
+ // -1, //L2I, // -
+ // -1, //L2F, // -
+ // 0, //L2D, // -
+ // 0, //F2I, // -
+ // 1, //F2L, // -
+ // 1, //F2D, // -
+ // -1, //D2I, // -
+ // 0, //D2L, // -
+ // -1, //D2F, // -
+ // 0, //I2B, // -
+ // 0, //I2C, // -
+ // 0, //I2S, // -
+ // -3, //LCMP, // -
+ // -1, //FCMPL, // -
+ // -1, //FCMPG, // -
+ // -3, //DCMPL, // -
+ // -3, //DCMPG, // -
+ // -1, //IFEQ, // visitJumpInsn
+ // -1, //IFNE, // -
+ // -1, //IFLT, // -
+ // -1, //IFGE, // -
+ // -1, //IFGT, // -
+ // -1, //IFLE, // -
+ // -2, //IF_ICMPEQ, // -
+ // -2, //IF_ICMPNE, // -
+ // -2, //IF_ICMPLT, // -
+ // -2, //IF_ICMPGE, // -
+ // -2, //IF_ICMPGT, // -
+ // -2, //IF_ICMPLE, // -
+ // -2, //IF_ACMPEQ, // -
+ // -2, //IF_ACMPNE, // -
+ // 0, //GOTO, // -
+ // 1, //JSR, // -
+ // 0, //RET, // visitVarInsn
+ // -1, //TABLESWITCH, // visiTableSwitchInsn
+ // -1, //LOOKUPSWITCH, // visitLookupSwitch
+ // -1, //IRETURN, // visitInsn
+ // -2, //LRETURN, // -
+ // -1, //FRETURN, // -
+ // -2, //DRETURN, // -
+ // -1, //ARETURN, // -
+ // 0, //RETURN, // -
+ // NA, //GETSTATIC, // visitFieldInsn
+ // NA, //PUTSTATIC, // -
+ // NA, //GETFIELD, // -
+ // NA, //PUTFIELD, // -
+ // NA, //INVOKEVIRTUAL, // visitMethodInsn
+ // NA, //INVOKESPECIAL, // -
+ // NA, //INVOKESTATIC, // -
+ // NA, //INVOKEINTERFACE, // -
+ // NA, //UNUSED, // NOT VISITED
+ // 1, //NEW, // visitTypeInsn
+ // 0, //NEWARRAY, // visitIntInsn
+ // 0, //ANEWARRAY, // visitTypeInsn
+ // 0, //ARRAYLENGTH, // visitInsn
+ // NA, //ATHROW, // -
+ // 0, //CHECKCAST, // visitTypeInsn
+ // 0, //INSTANCEOF, // -
+ // -1, //MONITORENTER, // visitInsn
+ // -1, //MONITOREXIT, // -
+ // NA, //WIDE, // NOT VISITED
+ // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
+ // -1, //IFNULL, // visitJumpInsn
+ // -1, //IFNONNULL, // -
+ // NA, //GOTO_W, // -
+ // NA, //JSR_W, // -
+ // };
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('E' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ /**
+ * The label (i.e. basic block) to which these input and output stack map
+ * frames correspond.
+ */
+ Label owner;
+
+ /**
+ * The input stack map frame locals.
+ */
+ int[] inputLocals;
+
+ /**
+ * The input stack map frame stack.
+ */
+ int[] inputStack;
+
+ /**
+ * The output stack map frame locals.
+ */
+ private int[] outputLocals;
+
+ /**
+ * The output stack map frame stack.
+ */
+ private int[] outputStack;
+
+ /**
+ * Relative size of the output stack. The exact semantics of this field
+ * depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the size of
+ * the output stack relatively to the top of the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * actual number of types in {@link #outputStack}.
+ */
+ private int outputStackTop;
+
+ /**
+ * Number of types that are initialized in the basic block.
+ *
+ * @see #initializations
+ */
+ private int initializationCount;
+
+ /**
+ * The types that are initialized in the basic block. A constructor
+ * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
+ * <i>every occurence</i> of this type in the local variables and in the
+ * operand stack. This cannot be done during the first phase of the
+ * algorithm since, during this phase, the local variables and the operand
+ * stack are not completely computed. It is therefore necessary to store the
+ * types on which constructors are invoked in the basic block, in order to
+ * do this replacement during the second phase of the algorithm, where the
+ * frames are fully computed. Note that this array can contain types that
+ * are relative to input locals or to the input stack (see below for the
+ * description of the algorithm).
+ */
+ private int[] initializations;
+
+ /**
+ * Returns the int encoding of the given type.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param desc a type descriptor.
+ * @return the int encoding of the given type.
+ */
+ private static int type(final ClassWriter cw, final String desc) {
+ String t;
+ int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+ switch (desc.charAt(index)) {
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ // stores the internal name, not the descriptor!
+ t = desc.substring(index + 1, desc.length() - 1);
+ return OBJECT | cw.addType(t);
+ // case '[':
+ default:
+ // extracts the dimensions and the element type
+ int data;
+ int dims = index + 1;
+ while (desc.charAt(dims) == '[') {
+ ++dims;
+ }
+ switch (desc.charAt(dims)) {
+ case 'Z':
+ data = BOOLEAN;
+ break;
+ case 'C':
+ data = CHAR;
+ break;
+ case 'B':
+ data = BYTE;
+ break;
+ case 'S':
+ data = SHORT;
+ break;
+ case 'I':
+ data = INTEGER;
+ break;
+ case 'F':
+ data = FLOAT;
+ break;
+ case 'J':
+ data = LONG;
+ break;
+ case 'D':
+ data = DOUBLE;
+ break;
+ // case 'L':
+ default:
+ // stores the internal name, not the descriptor
+ t = desc.substring(dims + 1, desc.length() - 1);
+ data = OBJECT | cw.addType(t);
+ }
+ return (dims - index) << 28 | data;
+ }
+ }
+
+ /**
+ * Merges the type at the given index in the given type array with the given
+ * type. Returns <tt>true</tt> if the type array has been modified by this
+ * operation.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param t the type with which the type array element must be merged.
+ * @param types an array of types.
+ * @param index the index of the type that must be merged in 'types'.
+ * @return <tt>true</tt> if the type array has been modified by this
+ * operation.
+ */
+ private static boolean merge(
+ final ClassWriter cw,
+ int t,
+ final int[] types,
+ final int index)
+ {
+ int u = types[index];
+ if (u == t) {
+ // if the types are equal, merge(u,t)=u, so there is no change
+ return false;
+ }
+ if ((t & ~DIM) == NULL) {
+ if (u == NULL) {
+ return false;
+ }
+ t = NULL;
+ }
+ if (u == 0) {
+ // if types[index] has never been assigned, merge(u,t)=t
+ types[index] = t;
+ return true;
+ }
+ int v;
+ if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
+ // if u is a reference type of any dimension
+ if (t == NULL) {
+ // if t is the NULL type, merge(u,t)=u, so there is no change
+ return false;
+ } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ if ((u & BASE_KIND) == OBJECT) {
+ // if t is also a reference type, and if u and t have the
+ // same dimension merge(u,t) = dim(t) | common parent of the
+ // element types of u and t
+ v = (t & DIM) | OBJECT
+ | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
+ } else {
+ // if u and t are array types, but not with the same element
+ // type, merge(u,t)=java/lang/Object
+ v = OBJECT | cw.addType("java/lang/Object");
+ }
+ } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
+ // if t is any other reference or array type,
+ // merge(u,t)=java/lang/Object
+ v = OBJECT | cw.addType("java/lang/Object");
+ } else {
+ // if t is any other type, merge(u,t)=TOP
+ v = TOP;
+ }
+ } else if (u == NULL) {
+ // if u is the NULL type, merge(u,t)=t,
+ // or TOP if t is not a reference type
+ v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
+ } else {
+ // if u is any other type, merge(u,t)=TOP whatever t
+ v = TOP;
+ }
+ if (u != v) {
+ types[index] = v;
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the output frame local variable type at the given index.
+ *
+ * @param local the index of the local that must be returned.
+ * @return the output frame local variable type at the given index.
+ */
+ private int get(final int local) {
+ if (outputLocals == null || local >= outputLocals.length) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ return LOCAL | local;
+ } else {
+ int type = outputLocals[local];
+ if (type == 0) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ type = outputLocals[local] = LOCAL | local;
+ }
+ return type;
+ }
+ }
+
+ /**
+ * Sets the output frame local variable type at the given index.
+ *
+ * @param local the index of the local that must be set.
+ * @param type the value of the local that must be set.
+ */
+ private void set(final int local, final int type) {
+ // creates and/or resizes the output local variables array if necessary
+ if (outputLocals == null) {
+ outputLocals = new int[10];
+ }
+ int n = outputLocals.length;
+ if (local >= n) {
+ int[] t = new int[Math.max(local + 1, 2 * n)];
+ System.arraycopy(outputLocals, 0, t, 0, n);
+ outputLocals = t;
+ }
+ // sets the local variable
+ outputLocals[local] = type;
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param type the type that must be pushed.
+ */
+ private void push(final int type) {
+ // creates and/or resizes the output stack array if necessary
+ if (outputStack == null) {
+ outputStack = new int[10];
+ }
+ int n = outputStack.length;
+ if (outputStackTop >= n) {
+ int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
+ System.arraycopy(outputStack, 0, t, 0, n);
+ outputStack = t;
+ }
+ // pushes the type on the output stack
+ outputStack[outputStackTop++] = type;
+ // updates the maximun height reached by the output stack, if needed
+ int top = owner.inputStackTop + outputStackTop;
+ if (top > owner.outputStackMax) {
+ owner.outputStackMax = top;
+ }
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param desc the descriptor of the type to be pushed. Can also be a method
+ * descriptor (in this case this method pushes its return type onto
+ * the output frame stack).
+ */
+ private void push(final ClassWriter cw, final String desc) {
+ int type = type(cw, desc);
+ if (type != 0) {
+ push(type);
+ if (type == LONG || type == DOUBLE) {
+ push(TOP);
+ }
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack and returns its value.
+ *
+ * @return the type that has been popped from the output frame stack.
+ */
+ private int pop() {
+ if (outputStackTop > 0) {
+ return outputStack[--outputStackTop];
+ } else {
+ // if the output frame stack is empty, pops from the input stack
+ return STACK | -(--owner.inputStackTop);
+ }
+ }
+
+ /**
+ * Pops the given number of types from the output frame stack.
+ *
+ * @param elements the number of types that must be popped.
+ */
+ private void pop(final int elements) {
+ if (outputStackTop >= elements) {
+ outputStackTop -= elements;
+ } else {
+ // if the number of elements to be popped is greater than the number
+ // of elements in the output stack, clear it, and pops the remaining
+ // elements from the input stack.
+ owner.inputStackTop -= elements - outputStackTop;
+ outputStackTop = 0;
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack.
+ *
+ * @param desc the descriptor of the type to be popped. Can also be a method
+ * descriptor (in this case this method pops the types corresponding
+ * to the method arguments).
+ */
+ private void pop(final String desc) {
+ char c = desc.charAt(0);
+ if (c == '(') {
+ pop((MethodWriter.getArgumentsAndReturnSizes(desc) >> 2) - 1);
+ } else if (c == 'J' || c == 'D') {
+ pop(2);
+ } else {
+ pop(1);
+ }
+ }
+
+ /**
+ * Adds a new type to the list of types on which a constructor is invoked in
+ * the basic block.
+ *
+ * @param var a type on a which a constructor is invoked.
+ */
+ private void init(final int var) {
+ // creates and/or resizes the initializations array if necessary
+ if (initializations == null) {
+ initializations = new int[2];
+ }
+ int n = initializations.length;
+ if (initializationCount >= n) {
+ int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
+ System.arraycopy(initializations, 0, t, 0, n);
+ initializations = t;
+ }
+ // stores the type to be initialized
+ initializations[initializationCount++] = var;
+ }
+
+ /**
+ * Replaces the given type with the appropriate type if it is one of the
+ * types on which a constructor is invoked in the basic block.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param t a type
+ * @return t or, if t is one of the types on which a constructor is invoked
+ * in the basic block, the type corresponding to this constructor.
+ */
+ private int init(final ClassWriter cw, final int t) {
+ int s;
+ if (t == UNINITIALIZED_THIS) {
+ s = OBJECT | cw.addType(cw.thisName);
+ } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
+ String type = cw.typeTable[t & BASE_VALUE].strVal1;
+ s = OBJECT | cw.addType(type);
+ } else {
+ return t;
+ }
+ for (int j = 0; j < initializationCount; ++j) {
+ int u = initializations[j];
+ int dim = u & DIM;
+ int kind = u & KIND;
+ if (kind == LOCAL) {
+ u = dim + inputLocals[u & VALUE];
+ } else if (kind == STACK) {
+ u = dim + inputStack[inputStack.length - (u & VALUE)];
+ }
+ if (t == u) {
+ return s;
+ }
+ }
+ return t;
+ }
+
+ /**
+ * Initializes the input frame of the first basic block from the method
+ * descriptor.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param access the access flags of the method to which this label belongs.
+ * @param args the formal parameter types of this method.
+ * @param maxLocals the maximum number of local variables of this method.
+ */
+ void initInputFrame(
+ final ClassWriter cw,
+ final int access,
+ final Type[] args,
+ final int maxLocals)
+ {
+ inputLocals = new int[maxLocals];
+ inputStack = new int[0];
+ int i = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
+ inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
+ } else {
+ inputLocals[i++] = UNINITIALIZED_THIS;
+ }
+ }
+ for (int j = 0; j < args.length; ++j) {
+ int t = type(cw, args[j].getDescriptor());
+ inputLocals[i++] = t;
+ if (t == LONG || t == DOUBLE) {
+ inputLocals[i++] = TOP;
+ }
+ }
+ while (i < maxLocals) {
+ inputLocals[i++] = TOP;
+ }
+ }
+
+ /**
+ * Simulates the action of the given instruction on the output stack frame.
+ *
+ * @param opcode the opcode of the instruction.
+ * @param arg the operand of the instruction, if any.
+ * @param cw the class writer to which this label belongs.
+ * @param item the operand of the instructions, if any.
+ */
+ void execute(
+ final int opcode,
+ final int arg,
+ final ClassWriter cw,
+ final Item item)
+ {
+ int t1, t2, t3, t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (item.type) {
+ case ClassWriter.INT:
+ push(INTEGER);
+ break;
+ case ClassWriter.LONG:
+ push(LONG);
+ push(TOP);
+ break;
+ case ClassWriter.FLOAT:
+ push(FLOAT);
+ break;
+ case ClassWriter.DOUBLE:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case ClassWriter.CLASS:
+ push(OBJECT | cw.addType("java/lang/Class"));
+ break;
+ // case ClassWriter.STR:
+ default:
+ push(OBJECT | cw.addType("java/lang/String"));
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(get(arg));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ push(ELEMENT_OF + t1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(arg, t1);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(arg, t1);
+ set(arg + 1, TOP);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ set(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException("JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(item.strVal3);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(item.strVal3);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(item.strVal3);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ t1 = pop();
+ if (opcode == Opcodes.INVOKESPECIAL
+ && item.strVal2.charAt(0) == '<')
+ {
+ init(t1);
+ }
+ }
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
+ break;
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
+ break;
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
+ break;
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
+ break;
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
+ break;
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
+ break;
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
+ break;
+ // case Opcodes.T_LONG:
+ default:
+ push(ARRAY_OF | LONG);
+ break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, '[' + s);
+ } else {
+ push(ARRAY_OF | OBJECT | cw.addType(s));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, s);
+ } else {
+ push(OBJECT | cw.addType(s));
+ }
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(arg);
+ push(cw, item.strVal1);
+ break;
+ }
+ }
+
+ /**
+ * Merges the input frame of the given basic block with the input and output
+ * frames of this basic block. Returns <tt>true</tt> if the input frame of
+ * the given label has been changed by this operation.
+ *
+ * @param cw the ClassWriter to which this label belongs.
+ * @param frame the basic block whose input frame must be updated.
+ * @param edge the kind of the {@link Edge} between this label and 'label'.
+ * See {@link Edge#info}.
+ * @return <tt>true</tt> if the input frame of the given label has been
+ * changed by this operation.
+ */
+ boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
+ boolean changed = false;
+ int i, s, dim, kind, t;
+
+ int nLocal = inputLocals.length;
+ int nStack = inputStack.length;
+ if (frame.inputLocals == null) {
+ frame.inputLocals = new int[nLocal];
+ changed = true;
+ }
+
+ for (i = 0; i < nLocal; ++i) {
+ if (outputLocals != null && i < outputLocals.length) {
+ s = outputLocals[i];
+ if (s == 0) {
+ t = inputLocals[i];
+ } else {
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else if (kind == STACK) {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ } else {
+ t = s;
+ }
+ }
+ } else {
+ t = inputLocals[i];
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+
+ if (edge > 0) {
+ for (i = 0; i < nLocal; ++i) {
+ t = inputLocals[i];
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[1];
+ changed = true;
+ }
+ changed |= merge(cw, edge, frame.inputStack, 0);
+ return changed;
+ }
+
+ int nInputStack = inputStack.length + owner.inputStackTop;
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[nInputStack + outputStackTop];
+ changed = true;
+ }
+
+ for (i = 0; i < nInputStack; ++i) {
+ t = inputStack[i];
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, i);
+ }
+ for (i = 0; i < outputStackTop; ++i) {
+ s = outputStack[i];
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else if (kind == STACK) {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ } else {
+ t = s;
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, nInputStack + i);
+ }
+ return changed;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Handler.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Handler.java
new file mode 100644
index 0000000..9c935c5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Handler.java
@@ -0,0 +1,70 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * Information about an exception handler block.
+ *
+ * @author Eric Bruneton
+ */
+class Handler {
+
+ /**
+ * Beginning of the exception handler's scope (inclusive).
+ */
+ Label start;
+
+ /**
+ * End of the exception handler's scope (exclusive).
+ */
+ Label end;
+
+ /**
+ * Beginning of the exception handler's code.
+ */
+ Label handler;
+
+ /**
+ * Internal name of the type of exceptions handled by this handler, or
+ * <tt>null</tt> to catch any exceptions.
+ */
+ String desc;
+
+ /**
+ * Constant pool index of the internal name of the type of exceptions
+ * handled by this handler, or 0 to catch any exceptions.
+ */
+ int type;
+
+ /**
+ * Next exception handler block info.
+ */
+ Handler next;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Item.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Item.java
new file mode 100644
index 0000000..85fce2d
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Item.java
@@ -0,0 +1,256 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A constant pool item. Constant pool items can be created with the 'newXXX'
+ * methods in the {@link ClassWriter} class.
+ *
+ * @author Eric Bruneton
+ */
+final class Item {
+
+ /**
+ * Index of this item in the constant pool.
+ */
+ int index;
+
+ /**
+ * Type of this constant pool item. A single class is used to represent all
+ * constant pool item types, in order to minimize the bytecode size of this
+ * package. The value of this field is one of {@link ClassWriter#INT},
+ * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
+ * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
+ * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
+ * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
+ * {@link ClassWriter#METH}, {@link ClassWriter#IMETH}.
+ *
+ * Special Item types are used for Items that are stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table. These special item types are
+ * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
+ * {@link ClassWriter#TYPE_MERGED}.
+ */
+ int type;
+
+ /**
+ * Value of this item, for an integer item.
+ */
+ int intVal;
+
+ /**
+ * Value of this item, for a long item.
+ */
+ long longVal;
+
+ /**
+ * First part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal1;
+
+ /**
+ * Second part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal2;
+
+ /**
+ * Third part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal3;
+
+ /**
+ * The hash code value of this constant pool item.
+ */
+ int hashCode;
+
+ /**
+ * Link to another constant pool item, used for collision lists in the
+ * constant pool's hash table.
+ */
+ Item next;
+
+ /**
+ * Constructs an uninitialized {@link Item}.
+ */
+ Item() {
+ }
+
+ /**
+ * Constructs an uninitialized {@link Item} for constant pool element at
+ * given position.
+ *
+ * @param index index of the item to be constructed.
+ */
+ Item(final int index) {
+ this.index = index;
+ }
+
+ /**
+ * Constructs a copy of the given item.
+ *
+ * @param index index of the item to be constructed.
+ * @param i the item that must be copied into the item to be constructed.
+ */
+ Item(final int index, final Item i) {
+ this.index = index;
+ type = i.type;
+ intVal = i.intVal;
+ longVal = i.longVal;
+ strVal1 = i.strVal1;
+ strVal2 = i.strVal2;
+ strVal3 = i.strVal3;
+ hashCode = i.hashCode;
+ }
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = ClassWriter.INT;
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
+
+ /**
+ * Sets this item to a long item.
+ *
+ * @param longVal the value of this item.
+ */
+ void set(final long longVal) {
+ this.type = ClassWriter.LONG;
+ this.longVal = longVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+ }
+
+ /**
+ * Sets this item to a float item.
+ *
+ * @param floatVal the value of this item.
+ */
+ void set(final float floatVal) {
+ this.type = ClassWriter.FLOAT;
+ this.intVal = Float.floatToRawIntBits(floatVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+ }
+
+ /**
+ * Sets this item to a double item.
+ *
+ * @param doubleVal the value of this item.
+ */
+ void set(final double doubleVal) {
+ this.type = ClassWriter.DOUBLE;
+ this.longVal = Double.doubleToRawLongBits(doubleVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+ }
+
+ /**
+ * Sets this item to an item that do not hold a primitive value.
+ *
+ * @param type the type of this item.
+ * @param strVal1 first part of the value of this item.
+ * @param strVal2 second part of the value of this item.
+ * @param strVal3 third part of the value of this item.
+ */
+ void set(
+ final int type,
+ final String strVal1,
+ final String strVal2,
+ final String strVal3)
+ {
+ this.type = type;
+ this.strVal1 = strVal1;
+ this.strVal2 = strVal2;
+ this.strVal3 = strVal3;
+ switch (type) {
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.TYPE_NORMAL:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case ClassWriter.NAME_TYPE:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
+ }
+ }
+
+ /**
+ * Indicates if the given item is equal to this one.
+ *
+ * @param i the item to be compared to this one.
+ * @return <tt>true</tt> if the given item if equal to this one,
+ * <tt>false</tt> otherwise.
+ */
+ boolean isEqualTo(final Item i) {
+ if (i.type == type) {
+ switch (type) {
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ return i.intVal == intVal;
+ case ClassWriter.TYPE_MERGED:
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ return i.longVal == longVal;
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.TYPE_NORMAL:
+ return i.strVal1.equals(strVal1);
+ case ClassWriter.TYPE_UNINIT:
+ return i.intVal == intVal && i.strVal1.equals(strVal1);
+ case ClassWriter.NAME_TYPE:
+ return i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2);
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ default:
+ return i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2)
+ && i.strVal3.equals(strVal3);
+ }
+ }
+ return false;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Label.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Label.java
new file mode 100644
index 0000000..b40dee8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Label.java
@@ -0,0 +1,518 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A label represents a position in the bytecode of a method. Labels are used
+ * for jump, goto, and switch instructions, and for try catch blocks.
+ *
+ * @author Eric Bruneton
+ */
+public class Label {
+
+ /**
+ * Indicates if this label is only used for debug attributes. Such a label
+ * is not the start of a basic block, the target of a jump instruction, or
+ * an exception handler. It can be safely ignored in control flow graph
+ * analysis algorithms (for optimization purposes).
+ */
+ static final int DEBUG = 1;
+
+ /**
+ * Indicates if the position of this label is known.
+ */
+ static final int RESOLVED = 2;
+
+ /**
+ * Indicates if this label has been updated, after instruction resizing.
+ */
+ static final int RESIZED = 4;
+
+ /**
+ * Indicates if this basic block has been pushed in the basic block stack.
+ * See {@link MethodWriter#visitMaxs visitMaxs}.
+ */
+ static final int PUSHED = 8;
+
+ /**
+ * Indicates if this label is the target of a jump instruction, or the start
+ * of an exception handler.
+ */
+ static final int TARGET = 16;
+
+ /**
+ * Indicates if a stack map frame must be stored for this label.
+ */
+ static final int STORE = 32;
+
+ /**
+ * Indicates if this label corresponds to a reachable basic block.
+ */
+ static final int REACHABLE = 64;
+
+ /**
+ * Indicates if this basic block ends with a JSR instruction.
+ */
+ static final int JSR = 128;
+
+ /**
+ * Indicates if this basic block ends with a RET instruction.
+ */
+ static final int RET = 256;
+
+ /**
+ * Indicates if this basic block is the start of a subroutine.
+ */
+ static final int SUBROUTINE = 512;
+
+ /**
+ * Indicates if this subroutine basic block has been visited.
+ */
+ static final int VISITED = 1024;
+
+ /**
+ * Field used to associate user information to a label. Warning: this field
+ * is used by the ASM tree package. In order to use it with the ASM tree
+ * package you must override the {@link
+ * org.powermock.api.mockito.repackaged.asm.tree.MethodNode#getLabelNode} method.
+ */
+ public Object info;
+
+ /**
+ * Flags that indicate the status of this label.
+ *
+ * @see #DEBUG
+ * @see #RESOLVED
+ * @see #RESIZED
+ * @see #PUSHED
+ * @see #TARGET
+ * @see #STORE
+ * @see #REACHABLE
+ * @see #JSR
+ * @see #RET
+ */
+ int status;
+
+ /**
+ * The line number corresponding to this label, if known.
+ */
+ int line;
+
+ /**
+ * The position of this label in the code, if known.
+ */
+ int position;
+ /**
+ * Start of the output stack relatively to the input stack. The exact
+ * semantics of this field depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the number of
+ * elements in the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * offset of the first output stack element relatively to the top of the
+ * input stack. This offset is always negative or null. A null offset means
+ * that the output stack must be appended to the input stack. A -n offset
+ * means that the first n output stack elements must replace the top n input
+ * stack elements, and that the other elements must be appended to the input
+ * stack.
+ */
+ int inputStackTop;
+ /**
+ * Maximum height reached by the output stack, relatively to the top of the
+ * input stack. This maximum is always positive or null.
+ */
+ int outputStackMax;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow and data flow graph analysis algorithms (used
+ * to compute the maximum stack size or the stack map frames). A control
+ * flow graph contains one node per "basic block", and one edge per "jump"
+ * from one basic block to another. Each node (i.e., each basic block) is
+ * represented by the Label object that corresponds to the first instruction
+ * of this basic block. Each node also stores the list of its successors in
+ * the graph, as a linked list of Edge objects.
+ *
+ * The control flow analysis algorithms used to compute the maximum stack
+ * size or the stack map frames are similar and use two steps. The first
+ * step, during the visit of each instruction, builds information about the
+ * state of the local variables and the operand stack at the end of each
+ * basic block, called the "output frame", <i>relatively</i> to the frame
+ * state at the beginning of the basic block, which is called the "input
+ * frame", and which is <i>unknown</i> during this step. The second step,
+ * in {@link MethodWriter#visitMaxs}, is a fix point algorithm that
+ * computes information about the input frame of each basic block, from the
+ * input state of the first basic block (known from the method signature),
+ * and by the using the previously computed relative output frames.
+ *
+ * The algorithm used to compute the maximum stack size only computes the
+ * relative output and absolute input stack heights, while the algorithm
+ * used to compute stack map frames computes relative output frames and
+ * absolute input frames.
+ */
+ /**
+ * Information about the input and output stack map frames of this basic
+ * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
+ * option is used.
+ */
+ Frame frame;
+ /**
+ * The successor of this label, in the order they are visited. This linked
+ * list does not include labels used for debug info only. If
+ * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
+ * does not contain successive labels that denote the same bytecode position
+ * (in this case only the first label appears in this list).
+ */
+ Label successor;
+ /**
+ * The successors of this node in the control flow graph. These successors
+ * are stored in a linked list of {@link Edge Edge} objects, linked to each
+ * other by their {@link Edge#next} field.
+ */
+ Edge successors;
+ /**
+ * The next basic block in the basic block stack. This stack is used in the
+ * main loop of the fix point algorithm used in the second step of the
+ * control flow analysis algorithms.
+ *
+ * @see MethodWriter#visitMaxs
+ */
+ Label next;
+ /**
+ * Number of forward references to this label, times two.
+ */
+ private int referenceCount;
+ /**
+ * Informations about forward references. Each forward reference is
+ * described by two consecutive integers in this array: the first one is the
+ * position of the first byte of the bytecode instruction that contains the
+ * forward reference, while the second is the position of the first byte of
+ * the forward reference itself. In fact the sign of the first integer
+ * indicates if this reference uses 2 or 4 bytes, and its absolute value
+ * gives the position of the bytecode instruction. This array is also used
+ * as a bitset to store the subroutines to which a basic block belongs. This
+ * information is needed in {@linked MethodWriter#visitMaxs}, after all
+ * forward references have been resolved. Hence the same array can be used
+ * for both purposes without problems.
+ */
+ private int[] srcAndRefPositions;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new label.
+ */
+ public Label() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods to compute offsets and to manage forward references
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the offset corresponding to this label. This offset is computed
+ * from the start of the method's bytecode. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @return the offset corresponding to this label.
+ * @throws IllegalStateException if this label is not resolved yet.
+ */
+ public int getOffset() {
+ if ((status & RESOLVED) == 0) {
+ throw new IllegalStateException("Label offset position has not been resolved yet");
+ }
+ return position;
+ }
+
+ /**
+ * Puts a reference to this label in the bytecode of a method. If the
+ * position of the label is known, the offset is computed and written
+ * directly. Otherwise, a null offset is written and a new forward reference
+ * is declared for this label.
+ *
+ * @param owner the code writer that calls this method.
+ * @param out the bytecode of the method.
+ * @param source the position of first byte of the bytecode instruction that
+ * contains this label.
+ * @param wideOffset <tt>true</tt> if the reference must be stored in 4
+ * bytes, or <tt>false</tt> if it must be stored with 2 bytes.
+ * @throws IllegalArgumentException if this label has not been created by
+ * the given code writer.
+ */
+ void put(
+ final MethodWriter owner,
+ final ByteVector out,
+ final int source,
+ final boolean wideOffset)
+ {
+ if ((status & RESOLVED) == 0) {
+ if (wideOffset) {
+ addReference(-1 - source, out.length);
+ out.putInt(-1);
+ } else {
+ addReference(source, out.length);
+ out.putShort(-1);
+ }
+ } else {
+ if (wideOffset) {
+ out.putInt(position - source);
+ } else {
+ out.putShort(position - source);
+ }
+ }
+ }
+
+ /**
+ * Adds a forward reference to this label. This method must be called only
+ * for a true forward reference, i.e. only if this label is not resolved
+ * yet. For backward references, the offset of the reference can be, and
+ * must be, computed and stored directly.
+ *
+ * @param sourcePosition the position of the referencing instruction. This
+ * position will be used to compute the offset of this forward
+ * reference.
+ * @param referencePosition the position where the offset for this forward
+ * reference must be stored.
+ */
+ private void addReference(
+ final int sourcePosition,
+ final int referencePosition)
+ {
+ if (srcAndRefPositions == null) {
+ srcAndRefPositions = new int[6];
+ }
+ if (referenceCount >= srcAndRefPositions.length) {
+ int[] a = new int[srcAndRefPositions.length + 6];
+ System.arraycopy(srcAndRefPositions,
+ 0,
+ a,
+ 0,
+ srcAndRefPositions.length);
+ srcAndRefPositions = a;
+ }
+ srcAndRefPositions[referenceCount++] = sourcePosition;
+ srcAndRefPositions[referenceCount++] = referencePosition;
+ }
+
+ /**
+ * Resolves all forward references to this label. This method must be called
+ * when this label is added to the bytecode of the method, i.e. when its
+ * position becomes known. This method fills in the blanks that where left
+ * in the bytecode by each forward reference previously added to this label.
+ *
+ * @param owner the code writer that calls this method.
+ * @param position the position of this label in the bytecode.
+ * @param data the bytecode of the method.
+ * @return <tt>true</tt> if a blank that was left for this label was to
+ * small to store the offset. In such a case the corresponding jump
+ * instruction is replaced with a pseudo instruction (using unused
+ * opcodes) using an unsigned two bytes offset. These pseudo
+ * instructions will need to be replaced with true instructions with
+ * wider offsets (4 bytes instead of 2). This is done in
+ * {@link MethodWriter#resizeInstructions}.
+ * @throws IllegalArgumentException if this label has already been resolved,
+ * or if it has not been created by the given code writer.
+ */
+ boolean resolve(
+ final MethodWriter owner,
+ final int position,
+ final byte[] data)
+ {
+ boolean needUpdate = false;
+ this.status |= RESOLVED;
+ this.position = position;
+ int i = 0;
+ while (i < referenceCount) {
+ int source = srcAndRefPositions[i++];
+ int reference = srcAndRefPositions[i++];
+ int offset;
+ if (source >= 0) {
+ offset = position - source;
+ if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
+ /*
+ * changes the opcode of the jump instruction, in order to
+ * be able to find it later (see resizeInstructions in
+ * MethodWriter). These temporary opcodes are similar to
+ * jump instruction opcodes, except that the 2 bytes offset
+ * is unsigned (and can therefore represent values from 0 to
+ * 65535, which is sufficient since the size of a method is
+ * limited to 65535 bytes).
+ */
+ int opcode = data[reference - 1] & 0xFF;
+ if (opcode <= Opcodes.JSR) {
+ // changes IFEQ ... JSR to opcodes 202 to 217
+ data[reference - 1] = (byte) (opcode + 49);
+ } else {
+ // changes IFNULL and IFNONNULL to opcodes 218 and 219
+ data[reference - 1] = (byte) (opcode + 20);
+ }
+ needUpdate = true;
+ }
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ } else {
+ offset = position + source + 1;
+ data[reference++] = (byte) (offset >>> 24);
+ data[reference++] = (byte) (offset >>> 16);
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ }
+ }
+ return needUpdate;
+ }
+
+ /**
+ * Returns the first label of the series to which this label belongs. For an
+ * isolated label or for the first label in a series of successive labels,
+ * this method returns the label itself. For other labels it returns the
+ * first label of the series.
+ *
+ * @return the first label of the series to which this label belongs.
+ */
+ Label getFirst() {
+ return !ClassReader.FRAMES || frame == null ? this : frame.owner;
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods related to subroutines
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns true is this basic block belongs to the given subroutine.
+ *
+ * @param id a subroutine id.
+ * @return true is this basic block belongs to the given subroutine.
+ */
+ boolean inSubroutine(final long id) {
+ if ((status & Label.VISITED) != 0) {
+ return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this basic block and the given one belong to a common
+ * subroutine.
+ *
+ * @param block another basic block.
+ * @return true if this basic block and the given one belong to a common
+ * subroutine.
+ */
+ boolean inSameSubroutine(final Label block) {
+ for (int i = 0; i < srcAndRefPositions.length; ++i) {
+ if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Marks this basic block as belonging to the given subroutine.
+ *
+ * @param id a subroutine id.
+ * @param nbSubroutines the total number of subroutines in the method.
+ */
+ void addToSubroutine(final long id, final int nbSubroutines) {
+ if ((status & VISITED) == 0) {
+ status |= VISITED;
+ srcAndRefPositions = new int[(nbSubroutines - 1) / 32 + 1];
+ }
+ srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
+ }
+
+ /**
+ * Finds the basic blocks that belong to a given subroutine, and marks these
+ * blocks as belonging to this subroutine. This recursive method follows the
+ * control flow graph to find all the blocks that are reachable from the
+ * current block WITHOUT following any JSR target.
+ *
+ * @param JSR a JSR block that jumps to this subroutine. If this JSR is not
+ * null it is added to the successor of the RET blocks found in the
+ * subroutine.
+ * @param id the id of this subroutine.
+ * @param nbSubroutines the total number of subroutines in the method.
+ */
+ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines)
+ {
+ if (JSR != null) {
+ if ((status & VISITED) != 0) {
+ return;
+ }
+ status |= VISITED;
+ // adds JSR to the successors of this block, if it is a RET block
+ if ((status & RET) != 0) {
+ if (!inSameSubroutine(JSR)) {
+ Edge e = new Edge();
+ e.info = inputStackTop;
+ e.successor = JSR.successors.successor;
+ e.next = successors;
+ successors = e;
+ }
+ }
+ } else {
+ // if this block already belongs to subroutine 'id', returns
+ if (inSubroutine(id)) {
+ return;
+ }
+ // marks this block as belonging to subroutine 'id'
+ addToSubroutine(id, nbSubroutines);
+ }
+ // calls this method recursively on each successor, except JSR targets
+ Edge e = successors;
+ while (e != null) {
+ // if this block is a JSR block, then 'successors.next' leads
+ // to the JSR target (see {@link #visitJumpInsn}) and must therefore
+ // not be followed
+ if ((status & Label.JSR) == 0 || e != successors.next) {
+ e.successor.visitSubroutine(JSR, id, nbSubroutines);
+ }
+ e = e.next;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Overriden Object methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns a string representation of this label.
+ *
+ * @return a string representation of this label.
+ */
+ public String toString() {
+ return "L" + System.identityHashCode(this);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodAdapter.java
new file mode 100644
index 0000000..90ed812
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodAdapter.java
@@ -0,0 +1,195 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * An empty {@link MethodVisitor} that delegates to another
+ * {@link MethodVisitor}. This class can be used as a super class to quickly
+ * implement usefull method adapter classes, just by overriding the necessary
+ * methods.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodAdapter implements MethodVisitor {
+
+ /**
+ * The {@link MethodVisitor} to which this adapter delegates calls.
+ */
+ protected MethodVisitor mv;
+
+ /**
+ * Constructs a new {@link MethodAdapter} object.
+ *
+ * @param mv the code visitor to which this adapter must delegate calls.
+ */
+ public MethodAdapter(final MethodVisitor mv) {
+ this.mv = mv;
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ return mv.visitAnnotationDefault();
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ return mv.visitAnnotation(desc, visible);
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ return mv.visitParameterAnnotation(parameter, desc, visible);
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ mv.visitAttribute(attr);
+ }
+
+ public void visitCode() {
+ mv.visitCode();
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ public void visitInsn(final int opcode) {
+ mv.visitInsn(opcode);
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ mv.visitIntInsn(opcode, operand);
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ mv.visitVarInsn(opcode, var);
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ mv.visitTypeInsn(opcode, type);
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ mv.visitJumpInsn(opcode, label);
+ }
+
+ public void visitLabel(final Label label) {
+ mv.visitLabel(label);
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ mv.visitLdcInsn(cst);
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ mv.visitIincInsn(var, increment);
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ mv.visitLineNumber(line, start);
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+
+ public void visitEnd() {
+ mv.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodVisitor.java
new file mode 100644
index 0000000..2046433
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodVisitor.java
@@ -0,0 +1,395 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A visitor to visit a Java method. The methods of this interface must be
+ * called in the following order: [ <tt>visitAnnotationDefault</tt> ] (
+ * <tt>visitAnnotation</tt> | <tt>visitParameterAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
+ * <tt>visit</tt><i>X</i>Insn</tt> | <tt>visitLabel</tt> | <tt>visitTryCatchBlock</tt> |
+ * <tt>visitLocalVariable</tt> | <tt>visitLineNumber</tt>)* <tt>visitMaxs</tt> ]
+ * <tt>visitEnd</tt>. In addition, the <tt>visit</tt><i>X</i>Insn</tt>
+ * and <tt>visitLabel</tt> methods must be called in the sequential order of
+ * the bytecode instructions of the visited code, <tt>visitTryCatchBlock</tt>
+ * must be called <i>before</i> the labels passed as arguments have been
+ * visited, and the <tt>visitLocalVariable</tt> and <tt>visitLineNumber</tt>
+ * methods must be called <i>after</i> the labels passed as arguments have been
+ * visited.
+ *
+ * @author Eric Bruneton
+ */
+public interface MethodVisitor {
+
+ // -------------------------------------------------------------------------
+ // Annotations and non standard attributes
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits the default value of this annotation interface method.
+ *
+ * @return a visitor to the visit the actual default value of this
+ * annotation interface method, or <tt>null</tt> if this visitor
+ * is not interested in visiting this default value. The 'name'
+ * parameters passed to the methods of this annotation visitor are
+ * ignored. Moreover, exacly one visit method must be called on this
+ * annotation visitor, followed by visitEnd.
+ */
+ AnnotationVisitor visitAnnotationDefault();
+
+ /**
+ * Visits an annotation of this method.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ AnnotationVisitor visitAnnotation(String desc, boolean visible);
+
+ /**
+ * Visits an annotation of a parameter this method.
+ *
+ * @param parameter the parameter index.
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ AnnotationVisitor visitParameterAnnotation(
+ int parameter,
+ String desc,
+ boolean visible);
+
+ /**
+ * Visits a non standard attribute of this method.
+ *
+ * @param attr an attribute.
+ */
+ void visitAttribute(Attribute attr);
+
+ /**
+ * Starts the visit of the method's code, if any (i.e. non abstract method).
+ */
+ void visitCode();
+
+ /**
+ * Visits the current state of the local variables and operand stack
+ * elements. This method must(*) be called <i>just before</i> any
+ * instruction <b>i</b> that follows an unconditionnal branch instruction
+ * such as GOTO or THROW, that is the target of a jump instruction, or that
+ * starts an exception handler block. The visited types must describe the
+ * values of the local variables and of the operand stack elements <i>just
+ * before</i> <b>i</b> is executed. <br> <br> (*) this is mandatory only
+ * for classes whose version is greater than or equal to
+ * {@link Opcodes#V1_6 V1_6}. <br> <br> Packed frames are basically
+ * "deltas" from the state of the previous frame (very first frame is
+ * implicitly defined by the method's parameters and access flags): <ul>
+ * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
+ * locals as the previous frame and with the empty stack.</li> <li>{@link Opcodes#F_SAME1}
+ * representing frame with exactly the same locals as the previous frame and
+ * with single value on the stack (<code>nStack</code> is 1 and
+ * <code>stack[0]</code> contains value for the type of the stack item).</li>
+ * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
+ * the same as the locals in the previous frame, except that additional
+ * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
+ * <code>local</code> elements contains values representing added types).</li>
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are
+ * the same as the locals in the previous frame, except that the last 1-3
+ * locals are absent and with the empty stack (<code>nLocals</code> is 1,
+ * 2 or 3). </li> <li>{@link Opcodes#F_FULL} representing complete frame
+ * data.</li> </li> </ul>
+ *
+ * @param type the type of this stack map frame. Must be
+ * {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed
+ * frames.
+ * @param nLocal the number of local variables in the visited frame.
+ * @param local the local variable types in this frame. This array must not
+ * be modified. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are represented
+ * by String objects (representing internal names), and uninitialized
+ * types by Label objects (this label designates the NEW instruction
+ * that created this uninitialized value).
+ * @param nStack the number of operand stack elements in the visited frame.
+ * @param stack the operand stack types in this frame. This array must not
+ * be modified. Its content has the same format as the "local" array.
+ */
+ void visitFrame(
+ int type,
+ int nLocal,
+ Object[] local,
+ int nStack,
+ Object[] stack);
+
+ // -------------------------------------------------------------------------
+ // Normal instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a zero operand instruction.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is
+ * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2,
+ * ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1, FCONST_0,
+ * FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD, FALOAD,
+ * DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE, FASTORE,
+ * DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2, DUP,
+ * DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD, FADD,
+ * DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV, LDIV,
+ * FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL,
+ * LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR,
+ * I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B,
+ * I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+ * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+ * MONITORENTER, or MONITOREXIT.
+ */
+ void visitInsn(int opcode);
+
+ /**
+ * Visits an instruction with a single int operand.
+ *
+ * @param opcode the opcode of the instruction to be visited. This opcode is
+ * either BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand the operand of the instruction to be visited.<br> When
+ * opcode is BIPUSH, operand value should be between Byte.MIN_VALUE
+ * and Byte.MAX_VALUE.<br> When opcode is SIPUSH, operand value
+ * should be between Short.MIN_VALUE and Short.MAX_VALUE.<br> When
+ * opcode is NEWARRAY, operand value should be one of
+ * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+ * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+ * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+ * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ */
+ void visitIntInsn(int opcode, int operand);
+
+ /**
+ * Visits a local variable instruction. A local variable instruction is an
+ * instruction that loads or stores the value of a local variable.
+ *
+ * @param opcode the opcode of the local variable instruction to be visited.
+ * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE,
+ * LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be visited. This operand is
+ * the index of a local variable.
+ */
+ void visitVarInsn(int opcode, int var);
+
+ /**
+ * Visits a type instruction. A type instruction is an instruction that
+ * takes the internal name of a class as parameter.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type the operand of the instruction to be visited. This operand
+ * must be the internal name of an object or array class (see {@link
+ * Type#getInternalName() getInternalName}).
+ */
+ void visitTypeInsn(int opcode, String type);
+
+ /**
+ * Visits a field instruction. A field instruction is an instruction that
+ * loads or stores the value of a field of an object.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see {@link
+ * Type#getInternalName() getInternalName}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link Type Type}).
+ */
+ void visitFieldInsn(int opcode, String owner, String name, String desc);
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see {@link
+ * Type#getInternalName() getInternalName}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type Type}).
+ */
+ void visitMethodInsn(int opcode, String owner, String name, String desc);
+
+ /**
+ * Visits a jump instruction. A jump instruction is an instruction that may
+ * jump to another instruction.
+ *
+ * @param opcode the opcode of the type instruction to be visited. This
+ * opcode is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be visited. This operand
+ * is a label that designates the instruction to which the jump
+ * instruction may jump.
+ */
+ void visitJumpInsn(int opcode, Label label);
+
+ /**
+ * Visits a label. A label designates the instruction that will be visited
+ * just after it.
+ *
+ * @param label a {@link Label Label} object.
+ */
+ void visitLabel(Label label);
+
+ // -------------------------------------------------------------------------
+ // Special instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a LDC instruction.
+ *
+ * @param cst the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} a {@link String} (or a {@link Type} for
+ * <tt>.class</tt> constants, for classes whose version is 49.0 or
+ * more).
+ */
+ void visitLdcInsn(Object cst);
+
+ /**
+ * Visits an IINC instruction.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param increment amount to increment the local variable by.
+ */
+ void visitIincInsn(int var, int increment);
+
+ /**
+ * Visits a TABLESWITCH instruction.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ void visitTableSwitchInsn(int min, int max, Label dflt, Label[] labels);
+
+ /**
+ * Visits a LOOKUPSWITCH instruction.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ */
+ void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels);
+
+ /**
+ * Visits a MULTIANEWARRAY instruction.
+ *
+ * @param desc an array type descriptor (see {@link Type Type}).
+ * @param dims number of dimensions of the array to allocate.
+ */
+ void visitMultiANewArrayInsn(String desc, int dims);
+
+ // -------------------------------------------------------------------------
+ // Exceptions table entries, debug information, max stack and max locals
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a try catch block.
+ *
+ * @param start beginning of the exception handler's scope (inclusive).
+ * @param end end of the exception handler's scope (exclusive).
+ * @param handler beginning of the exception handler's code.
+ * @param type internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for "finally"
+ * blocks).
+ * @throws IllegalArgumentException if one of the labels has already been
+ * visited by this visitor (by the {@link #visitLabel visitLabel}
+ * method).
+ */
+ void visitTryCatchBlock(Label start, Label end, Label handler, String type);
+
+ /**
+ * Visits a local variable declaration.
+ *
+ * @param name the name of a local variable.
+ * @param desc the type descriptor of this local variable.
+ * @param signature the type signature of this local variable. May be
+ * <tt>null</tt> if the local variable type does not use generic
+ * types.
+ * @param start the first instruction corresponding to the scope of this
+ * local variable (inclusive).
+ * @param end the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index the local variable's index.
+ * @throws IllegalArgumentException if one of the labels has not already
+ * been visited by this visitor (by the
+ * {@link #visitLabel visitLabel} method).
+ */
+ void visitLocalVariable(
+ String name,
+ String desc,
+ String signature,
+ Label start,
+ Label end,
+ int index);
+
+ /**
+ * Visits a line number declaration.
+ *
+ * @param line a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException if <tt>start</tt> has not already been
+ * visited by this visitor (by the {@link #visitLabel visitLabel}
+ * method).
+ */
+ void visitLineNumber(int line, Label start);
+
+ /**
+ * Visits the maximum stack size and the maximum number of local variables
+ * of the method.
+ *
+ * @param maxStack maximum stack size of the method.
+ * @param maxLocals maximum number of local variables for the method.
+ */
+ void visitMaxs(int maxStack, int maxLocals);
+
+ /**
+ * Visits the end of the method. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the method have been visited.
+ */
+ void visitEnd();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodWriter.java
new file mode 100644
index 0000000..0996e59
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/MethodWriter.java
@@ -0,0 +1,2564 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
+ * method of this class appends the bytecode corresponding to the visited
+ * instruction to a byte vector, in the order these methods are called.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+class MethodWriter implements MethodVisitor {
+
+ /**
+ * Pseudo access flag used to denote constructors.
+ */
+ static final int ACC_CONSTRUCTOR = 262144;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero.
+ */
+ static final int SAME_FRAME = 0; // to 63 (0-3f)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
+
+ /**
+ * Reserved for future use
+ */
+ static final int RESERVED = 128;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1. Offset is bigger then 63;
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that the k last locals are absent. The value of k is given
+ * by the formula 251-frame_type.
+ */
+ static final int CHOP_FRAME = 248; // to 250 (f8-fA)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero. Offset is bigger then 63;
+ */
+ static final int SAME_FRAME_EXTENDED = 251; // fb
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that k additional locals are defined. The value of k is
+ * given by the formula frame_type-251.
+ */
+ static final int APPEND_FRAME = 252; // to 254 // fc-fe
+
+ /**
+ * Full frame
+ */
+ static final int FULL_FRAME = 255; // ff
+
+ /**
+ * Indicates that the stack map frames must be recomputed from scratch. In
+ * this case the maximum stack size and number of local variables is also
+ * recomputed from scratch.
+ *
+ * @see #compute
+ */
+ private static final int FRAMES = 0;
+
+ /**
+ * Indicates that the maximum stack size and number of local variables must
+ * be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int MAXS = 1;
+
+ /**
+ * Indicates that nothing must be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int NOTHING = 2;
+ /**
+ * The class writer to which this method must be added.
+ */
+ final ClassWriter cw;
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * method.
+ */
+ private final int desc;
+ /**
+ * The descriptor of this method.
+ */
+ private final String descriptor;
+ /**
+ * Indicates what must be automatically computed.
+ *
+ * @see #FRAMES
+ * @see #MAXS
+ * @see #NOTHING
+ */
+ private final int compute;
+ /**
+ * Next method writer (see {@link ClassWriter#firstMethod firstMethod}).
+ */
+ MethodWriter next;
+ /**
+ * The signature of this method.
+ */
+ String signature;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the index of the first byte to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderOffset;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the number of bytes to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderLength;
+
+ /**
+ * Number of exceptions that can be thrown by this method.
+ */
+ int exceptionCount;
+
+ /**
+ * The exceptions that can be thrown by this method. More precisely, this
+ * array contains the indexes of the constant pool items that contain the
+ * internal names of these exception classes.
+ */
+ int[] exceptions;
+ /**
+ * Access flags of this method.
+ */
+ private int access;
+ /**
+ * The annotation default attribute of this method. May be <tt>null</tt>.
+ */
+ private ByteVector annd;
+ /**
+ * The runtime visible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+ /**
+ * The runtime invisible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+ /**
+ * The runtime visible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] panns;
+ /**
+ * The runtime invisible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] ipanns;
+ /**
+ * The number of synthetic parameters of this method.
+ */
+ private int synthetics;
+ /**
+ * The non standard attributes of the method.
+ */
+ private Attribute attrs;
+ /**
+ * The bytecode of this method.
+ */
+ private ByteVector code = new ByteVector();
+ /**
+ * Maximum stack size of this method.
+ */
+ private int maxStack;
+ /**
+ * Maximum number of local variables for this method.
+ */
+ private int maxLocals;
+ /**
+ * Number of stack map frames in the StackMapTable attribute.
+ */
+ private int frameCount;
+ /**
+ * The StackMapTable attribute.
+ */
+ private ByteVector stackMap;
+ /**
+ * The offset of the last frame that was written in the StackMapTable
+ * attribute.
+ */
+ private int previousFrameOffset;
+ /**
+ * The last frame that was written in the StackMapTable attribute.
+ *
+ * @see #frame
+ */
+ private int[] previousFrame;
+ /**
+ * Index of the next element to be added in {@link #frame}.
+ */
+ private int frameIndex;
+ /**
+ * The current stack map frame. The first element contains the offset of the
+ * instruction to which the frame corresponds, the second element is the
+ * number of locals and the third one is the number of stack elements. The
+ * local variables start at index 3 and are followed by the operand stack
+ * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
+ * nStack, frame[3] = nLocal. All types are encoded as integers, with the
+ * same format as the one used in {@link Label}, but limited to BASE types.
+ */
+ private int[] frame;
+ /**
+ * Number of elements in the exception handler list.
+ */
+ private int handlerCount;
+ /**
+ * The first element in the exception handler list.
+ */
+ private Handler firstHandler;
+ /**
+ * The last element in the exception handler list.
+ */
+ private Handler lastHandler;
+ /**
+ * Number of entries in the LocalVariableTable attribute.
+ */
+ private int localVarCount;
+ /**
+ * The LocalVariableTable attribute.
+ */
+ private ByteVector localVar;
+ /**
+ * Number of entries in the LocalVariableTypeTable attribute.
+ */
+ private int localVarTypeCount;
+ /**
+ * The LocalVariableTypeTable attribute.
+ */
+ private ByteVector localVarType;
+ /**
+ * Number of entries in the LineNumberTable attribute.
+ */
+ private int lineNumberCount;
+ /**
+ * The LineNumberTable attribute.
+ */
+ private ByteVector lineNumber;
+ /**
+ * The non standard attributes of the method's code.
+ */
+ private Attribute cattrs;
+ /**
+ * Indicates if some jump instructions are too small and need to be resized.
+ */
+ private boolean resize;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow graph analysis algorithm (used to compute the
+ * maximum stack size). A control flow graph contains one node per "basic
+ * block", and one edge per "jump" from one basic block to another. Each
+ * node (i.e., each basic block) is represented by the Label object that
+ * corresponds to the first instruction of this basic block. Each node also
+ * stores the list of its successors in the graph, as a linked list of Edge
+ * objects.
+ */
+ /**
+ * The number of subroutines in this method.
+ */
+ private int subroutines;
+ /**
+ * A list of labels. This list is the list of basic blocks in the method,
+ * i.e. a list of Label objects linked to each other by their
+ * {@link Label#successor} field, in the order they are visited by
+ * {@link MethodVisitor#visitLabel}, and starting with the first basic block.
+ */
+ private Label labels;
+
+ /**
+ * The previous basic block.
+ */
+ private Label previousBlock;
+
+ /**
+ * The current basic block.
+ */
+ private Label currentBlock;
+
+ /**
+ * The (relative) stack size after the last visited instruction. This size
+ * is relative to the beginning of the current basic block, i.e., the true
+ * stack size after the last visited instruction is equal to the
+ * {@link Label#inputStackTop beginStackSize} of the current basic block
+ * plus <tt>stackSize</tt>.
+ */
+ private int stackSize;
+
+ /**
+ * The (relative) maximum stack size after the last visited instruction.
+ * This size is relative to the beginning of the current basic block, i.e.,
+ * the true maximum stack size after the last visited instruction is equal
+ * to the {@link Label#inputStackTop beginStackSize} of the current basic
+ * block plus <tt>stackSize</tt>.
+ */
+ private int maxStackSize;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link MethodWriter}.
+ *
+ * @param cw the class writer in which the method must be added.
+ * @param access the method's access flags (see {@link Opcodes}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be <tt>null</tt>.
+ * @param exceptions the internal names of the method's exceptions. May be
+ * <tt>null</tt>.
+ * @param computeMaxs <tt>true</tt> if the maximum stack size and number
+ * of local variables must be automatically computed.
+ * @param computeFrames <tt>true</tt> if the stack map tables must be
+ * recomputed from scratch.
+ */
+ MethodWriter(
+ final ClassWriter cw,
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions,
+ final boolean computeMaxs,
+ final boolean computeFrames)
+ {
+ if (cw.firstMethod == null) {
+ cw.firstMethod = this;
+ } else {
+ cw.lastMethod.next = this;
+ }
+ cw.lastMethod = this;
+ this.cw = cw;
+ this.access = access;
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ this.descriptor = desc;
+ if (ClassReader.SIGNATURES) {
+ this.signature = signature;
+ }
+ if (exceptions != null && exceptions.length > 0) {
+ exceptionCount = exceptions.length;
+ this.exceptions = new int[exceptionCount];
+ for (int i = 0; i < exceptionCount; ++i) {
+ this.exceptions[i] = cw.newClass(exceptions[i]);
+ }
+ }
+ this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
+ if (computeMaxs || computeFrames) {
+ if (computeFrames && "<init>".equals(name)) {
+ this.access |= ACC_CONSTRUCTOR;
+ }
+ // updates maxLocals
+ int size = getArgumentsAndReturnSizes(descriptor) >> 2;
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ --size;
+ }
+ maxLocals = size;
+ // creates and visits the label for the first basic block
+ labels = new Label();
+ labels.status |= Label.PUSHED;
+ visitLabel(labels);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor interface
+ // ------------------------------------------------------------------------
+
+ /**
+ * Computes the size of the arguments and of the return value of a method.
+ *
+ * @param desc the descriptor of a method.
+ * @return the size of the arguments of the method (plus one for the
+ * implicit this argument), argSize, and the size of its return
+ * value, retSize, packed into a single int i =
+ * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal
+ * to <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+ */
+ static int getArgumentsAndReturnSizes(final String desc) {
+ int n = 1;
+ int c = 1;
+ while (true) {
+ char car = desc.charAt(c++);
+ if (car == ')') {
+ car = desc.charAt(c);
+ return n << 2
+ | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
+ } else if (car == 'L') {
+ while (desc.charAt(c++) != ';') {
+ }
+ n += 1;
+ } else if (car == '[') {
+ while ((car = desc.charAt(c)) == '[') {
+ ++c;
+ }
+ if (car == 'D' || car == 'J') {
+ n -= 1;
+ }
+ } else if (car == 'D' || car == 'J') {
+ n += 2;
+ } else {
+ n += 1;
+ }
+ }
+ }
+
+ /**
+ * Reads an unsigned short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readUnsignedShort(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static short readShort(final byte[] b, final int index) {
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readInt(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Writes a short value in the given byte array.
+ *
+ * @param b a byte array.
+ * @param index where the first byte of the short value must be written.
+ * @param s the value to be written in the given byte array.
+ */
+ static void writeShort(final byte[] b, final int index, final int s) {
+ b[index] = (byte) (s >>> 8);
+ b[index + 1] = (byte) s;
+ }
+
+ /**
+ * Computes the future value of a bytecode offset. <p> Note: it is possible
+ * to have several entries for the same instruction in the <tt>indexes</tt>
+ * and <tt>sizes</tt>: two entries (index=a,size=b) and (index=a,size=b')
+ * are equivalent to a single entry (index=a,size=b+b').
+ *
+ * @param indexes current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the <i>first</i>
+ * byte of the <i>next</i> instruction).
+ * @param sizes the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+ * bytes of the instruction will be removed (the instruction size
+ * <i>must not</i> become negative or null).
+ * @param begin index of the first byte of the source instruction.
+ * @param end index of the first byte of the target instruction.
+ * @return the future value of the given bytecode offset.
+ */
+ static int getNewOffset(
+ final int[] indexes,
+ final int[] sizes,
+ final int begin,
+ final int end)
+ {
+ int offset = end - begin;
+ for (int i = 0; i < indexes.length; ++i) {
+ if (begin < indexes[i] && indexes[i] <= end) {
+ // forward jump
+ offset += sizes[i];
+ } else if (end < indexes[i] && indexes[i] <= begin) {
+ // backward jump
+ offset -= sizes[i];
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Updates the offset of the given label.
+ *
+ * @param indexes current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the <i>first</i>
+ * byte of the <i>next</i> instruction).
+ * @param sizes the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |<tt>sizes[i]</tt>|
+ * bytes of the instruction will be removed (the instruction size
+ * <i>must not</i> become negative or null).
+ * @param label the label whose offset must be updated.
+ */
+ static void getNewOffset(
+ final int[] indexes,
+ final int[] sizes,
+ final Label label)
+ {
+ if ((label.status & Label.RESIZED) == 0) {
+ label.position = getNewOffset(indexes, sizes, 0, label.position);
+ label.status |= Label.RESIZED;
+ }
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ annd = new ByteVector();
+ return new AnnotationWriter(cw, false, annd, null, 0);
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ if ("Ljava/lang/Synthetic;".equals(desc)) {
+ // workaround for a bug in javac with synthetic parameters
+ // see ClassReader.readParameterAnnotations
+ synthetics = Math.max(synthetics, parameter + 1);
+ return new AnnotationWriter(cw, false, bv, null, 0);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ if (panns == null) {
+ panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = panns[parameter];
+ panns[parameter] = aw;
+ } else {
+ if (ipanns == null) {
+ ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = ipanns[parameter];
+ ipanns[parameter] = aw;
+ }
+ return aw;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ if (attr.isCodeAttribute()) {
+ attr.next = cattrs;
+ cattrs = attr;
+ } else {
+ attr.next = attrs;
+ attrs = attr;
+ }
+ }
+
+ public void visitCode() {
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ if (!ClassReader.FRAMES || compute == FRAMES) {
+ return;
+ }
+
+ if (type == Opcodes.F_NEW) {
+ startFrame(code.length, nLocal, nStack);
+ for (int i = 0; i < nLocal; ++i) {
+ if (local[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) local[i]);
+ } else if (local[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) local[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) local[i]).position);
+ }
+ }
+ for (int i = 0; i < nStack; ++i) {
+ if (stack[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) stack[i]);
+ } else if (stack[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) stack[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) stack[i]).position);
+ }
+ }
+ endFrame();
+ } else {
+ int delta;
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ delta = code.length;
+ } else {
+ delta = code.length - previousFrameOffset - 1;
+ }
+
+ switch (type) {
+ case Opcodes.F_FULL:
+ stackMap.putByte(FULL_FRAME)
+ .putShort(delta)
+ .putShort(nLocal);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ stackMap.putShort(nStack);
+ for (int i = 0; i < nStack; ++i) {
+ writeFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ stackMap.putByte(SAME_FRAME_EXTENDED + nLocal)
+ .putShort(delta);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ stackMap.putByte(SAME_FRAME_EXTENDED - nLocal)
+ .putShort(delta);
+ break;
+ case Opcodes.F_SAME:
+ if (delta < 64) {
+ stackMap.putByte(delta);
+ } else {
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (delta < 64) {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ } else {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(delta);
+ }
+ writeFrameType(stack[0]);
+ break;
+ }
+
+ previousFrameOffset = code.length;
+ ++frameCount;
+ }
+ }
+
+ public void visitInsn(final int opcode) {
+ // adds the instruction to the bytecode of the method
+ code.putByte(opcode);
+ // update currentBlock
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ } else {
+ // updates current and max stack sizes
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ // if opcode == ATHROW or xRETURN, ends current block (no successor)
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+ || opcode == Opcodes.ATHROW)
+ {
+ noSuccessor();
+ }
+ }
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, operand, null, null);
+ } else if (opcode != Opcodes.NEWARRAY) {
+ // updates current and max stack sizes only for NEWARRAY
+ // (stack size variation = 0 for BIPUSH or SIPUSH)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (opcode == Opcodes.SIPUSH) {
+ code.put12(opcode, operand);
+ } else { // BIPUSH or NEWARRAY
+ code.put11(opcode, operand);
+ }
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, var, null, null);
+ } else {
+ // updates current and max stack sizes
+ if (opcode == Opcodes.RET) {
+ // no stack change, but end of current block (no successor)
+ currentBlock.status |= Label.RET;
+ // save 'stackSize' here for future use
+ // (see {@link #findSubroutineSuccessors})
+ currentBlock.inputStackTop = stackSize;
+ noSuccessor();
+ } else { // xLOAD or xSTORE
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n;
+ if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE)
+ {
+ n = var + 2;
+ } else {
+ n = var + 1;
+ }
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (var < 4 && opcode != Opcodes.RET) {
+ int opt;
+ if (opcode < Opcodes.ISTORE) {
+ /* ILOAD_0 */
+ opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
+ } else {
+ /* ISTORE_0 */
+ opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
+ }
+ code.putByte(opt);
+ } else if (var >= 256) {
+ code.putByte(196 /* WIDE */).put12(opcode, var);
+ } else {
+ code.put11(opcode, var);
+ }
+ if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
+ visitLabel(new Label());
+ }
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ Item i = cw.newClassItem(type);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, code.length, cw, i);
+ } else if (opcode == Opcodes.NEW) {
+ // updates current and max stack sizes only if opcode == NEW
+ // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ Item i = cw.newFieldItem(owner, name, desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ char c = desc.charAt(0);
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+ break;
+ case Opcodes.PUTSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+ break;
+ case Opcodes.GETFIELD:
+ size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+ break;
+ // case Constants.PUTFIELD:
+ default:
+ size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+ break;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ Item i = cw.newMethodItem(owner, name, desc, itf);
+ int argSize = i.intVal;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ /*
+ * computes the stack size variation. In order not to recompute
+ * several times this variation for the same Item, we use the
+ * intVal field of this item to store this variation, once it
+ * has been computed. More precisely this intVal field stores
+ * the sizes of the arguments and of the return value
+ * corresponding to desc.
+ */
+ if (argSize == 0) {
+ // the above sizes have not been computed yet,
+ // so we compute them...
+ argSize = getArgumentsAndReturnSizes(desc);
+ // ... and we save them in order
+ // not to recompute them in the future
+ i.intVal = argSize;
+ }
+ int size;
+ if (opcode == Opcodes.INVOKESTATIC) {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+ } else {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03);
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (itf) {
+ if (argSize == 0) {
+ argSize = getArgumentsAndReturnSizes(desc);
+ i.intVal = argSize;
+ }
+ code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
+ } else {
+ code.put12(opcode, i.index);
+ }
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ Label nextInsn = null;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ // 'label' is the target of a jump instruction
+ label.getFirst().status |= Label.TARGET;
+ // adds 'label' as a successor of this basic block
+ addSuccessor(Edge.NORMAL, label);
+ if (opcode != Opcodes.GOTO) {
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ }
+ } else {
+ if (opcode == Opcodes.JSR) {
+ if ((label.status & Label.SUBROUTINE) == 0) {
+ label.status |= Label.SUBROUTINE;
+ ++subroutines;
+ }
+ currentBlock.status |= Label.JSR;
+ addSuccessor(stackSize + 1, label);
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ /*
+ * note that, by construction in this method, a JSR block
+ * has at least two successors in the control flow graph:
+ * the first one leads the next instruction after the JSR,
+ * while the second one leads to the JSR target.
+ */
+ } else {
+ // updates current stack size (max stack size unchanged
+ // because stack size variation always negative in this
+ // case)
+ stackSize += Frame.SIZE[opcode];
+ addSuccessor(stackSize, label);
+ }
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((label.status & Label.RESOLVED) != 0
+ && label.position - code.length < Short.MIN_VALUE)
+ {
+ /*
+ * case of a backward jump with an offset < -32768. In this case we
+ * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
+ * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
+ * designates the instruction just after the GOTO_W.
+ */
+ if (opcode == Opcodes.GOTO) {
+ code.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ code.putByte(201); // JSR_W
+ } else {
+ // if the IF instruction is transformed into IFNOT GOTO_W the
+ // next instruction becomes the target of the IFNOT instruction
+ if (nextInsn != null) {
+ nextInsn.status |= Label.TARGET;
+ }
+ code.putByte(opcode <= 166
+ ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ code.putShort(8); // jump offset
+ code.putByte(200); // GOTO_W
+ }
+ label.put(this, code, code.length - 1, true);
+ } else {
+ /*
+ * case of a backward jump with an offset >= -32768, or of a forward
+ * jump with, of course, an unknown offset. In these cases we store
+ * the offset in 2 bytes (which will be increased in
+ * resizeInstructions, if needed).
+ */
+ code.putByte(opcode);
+ label.put(this, code, code.length - 1, false);
+ }
+ if (currentBlock != null) {
+ if (nextInsn != null) {
+ // if the jump instruction is not a GOTO, the next instruction
+ // is also a successor of this instruction. Calling visitLabel
+ // adds the label of this next instruction as a successor of the
+ // current block, and starts a new basic block
+ visitLabel(nextInsn);
+ }
+ if (opcode == Opcodes.GOTO) {
+ noSuccessor();
+ }
+ }
+ }
+
+ public void visitLabel(final Label label) {
+ // resolves previous forward references to label, if any
+ resize |= label.resolve(this, code.length, code.data);
+ // updates currentBlock
+ if ((label.status & Label.DEBUG) != 0) {
+ return;
+ }
+ if (compute == FRAMES) {
+ if (currentBlock != null) {
+ if (label.position == currentBlock.position) {
+ // successive labels, do not start a new basic block
+ currentBlock.status |= (label.status & Label.TARGET);
+ label.frame = currentBlock.frame;
+ return;
+ }
+ // ends current block (with one new successor)
+ addSuccessor(Edge.NORMAL, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ if (label.frame == null) {
+ label.frame = new Frame();
+ label.frame.owner = label;
+ }
+ // updates the basic block list
+ if (previousBlock != null) {
+ if (label.position == previousBlock.position) {
+ previousBlock.status |= (label.status & Label.TARGET);
+ label.frame = previousBlock.frame;
+ currentBlock = previousBlock;
+ return;
+ }
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ } else if (compute == MAXS) {
+ if (currentBlock != null) {
+ // ends current block (with one new successor)
+ currentBlock.outputStackMax = maxStackSize;
+ addSuccessor(stackSize, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ // resets the relative current and max stack sizes
+ stackSize = 0;
+ maxStackSize = 0;
+ // updates the basic block list
+ if (previousBlock != null) {
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ }
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ Item i = cw.newConstItem(cst);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE)
+ {
+ size = stackSize + 2;
+ } else {
+ size = stackSize + 1;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ int index = i.index;
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
+ code.put12(20 /* LDC2_W */, index);
+ } else if (index >= 256) {
+ code.put12(19 /* LDC_W */, index);
+ } else {
+ code.put11(Opcodes.LDC, index);
+ }
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.IINC, var, null, null);
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n = var + 1;
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((var > 255) || (increment > 127) || (increment < -128)) {
+ code.putByte(196 /* WIDE */)
+ .put12(Opcodes.IINC, var)
+ .putShort(increment);
+ } else {
+ code.putByte(Opcodes.IINC).put11(var, increment);
+ }
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.TABLESWITCH);
+ code.length += (4 - code.length % 4) % 4;
+ dflt.put(this, code, source, true);
+ code.putInt(min).putInt(max);
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.LOOKUPSWITCH);
+ code.length += (4 - code.length % 4) % 4;
+ dflt.put(this, code, source, true);
+ code.putInt(labels.length);
+ for (int i = 0; i < labels.length; ++i) {
+ code.putInt(keys[i]);
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: control flow analysis algorithm
+ // ------------------------------------------------------------------------
+
+ private void visitSwitchInsn(final Label dflt, final Label[] labels) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
+ // adds current block successors
+ addSuccessor(Edge.NORMAL, dflt);
+ dflt.getFirst().status |= Label.TARGET;
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(Edge.NORMAL, labels[i]);
+ labels[i].getFirst().status |= Label.TARGET;
+ }
+ } else {
+ // updates current stack size (max stack size unchanged)
+ --stackSize;
+ // adds current block successors
+ addSuccessor(stackSize, dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(stackSize, labels[i]);
+ }
+ }
+ // ends current block
+ noSuccessor();
+ }
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ Item i = cw.newClassItem(desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
+ } else {
+ // updates current stack size (max stack size unchanged because
+ // stack size variation always negative or null)
+ stackSize += 1 - dims;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ ++handlerCount;
+ Handler h = new Handler();
+ h.start = start;
+ h.end = end;
+ h.handler = handler;
+ h.desc = type;
+ h.type = type != null ? cw.newClass(type) : 0;
+ if (lastHandler == null) {
+ firstHandler = h;
+ } else {
+ lastHandler.next = h;
+ }
+ lastHandler = h;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: stack map frames
+ // ------------------------------------------------------------------------
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ if (signature != null) {
+ if (localVarType == null) {
+ localVarType = new ByteVector();
+ }
+ ++localVarTypeCount;
+ localVarType.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name))
+ .putShort(cw.newUTF8(signature))
+ .putShort(index);
+ }
+ if (localVar == null) {
+ localVar = new ByteVector();
+ }
+ ++localVarCount;
+ localVar.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name))
+ .putShort(cw.newUTF8(desc))
+ .putShort(index);
+ if (compute != NOTHING) {
+ // updates max locals
+ char c = desc.charAt(0);
+ int n = index + (c == 'J' || c == 'D' ? 2 : 1);
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ if (lineNumber == null) {
+ lineNumber = new ByteVector();
+ }
+ ++lineNumberCount;
+ lineNumber.putShort(start.position);
+ lineNumber.putShort(line);
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (ClassReader.FRAMES && compute == FRAMES) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start.getFirst();
+ Label h = handler.handler.getFirst();
+ Label e = handler.end.getFirst();
+ // computes the kind of the edges to 'h'
+ String t = handler.desc == null
+ ? "java/lang/Throwable"
+ : handler.desc;
+ int kind = Frame.OBJECT | cw.addType(t);
+ // h is an exception handler
+ h.status |= Label.TARGET;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = kind;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ b.next = l.successors;
+ l.successors = b;
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ // creates and visits the first (implicit) frame
+ Frame f = labels.frame;
+ Type[] args = Type.getArgumentTypes(descriptor);
+ f.initInputFrame(cw, access, args, this.maxLocals);
+ visitFrame(f);
+
+ /*
+ * fix point algorithm: mark the first basic block as 'changed'
+ * (i.e. put it in the 'changed' list) and, while there are changed
+ * basic blocks, choose one, mark it as unchanged, and update its
+ * successors (which can be changed in the process).
+ */
+ int max = 0;
+ Label changed = labels;
+ while (changed != null) {
+ // removes a basic block from the list of changed basic blocks
+ Label l = changed;
+ changed = changed.next;
+ l.next = null;
+ f = l.frame;
+ // a reacheable jump target must be stored in the stack map
+ if ((l.status & Label.TARGET) != 0) {
+ l.status |= Label.STORE;
+ }
+ // all visited labels are reacheable, by definition
+ l.status |= Label.REACHABLE;
+ // updates the (absolute) maximum stack size
+ int blockMax = f.inputStack.length + l.outputStackMax;
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // updates the successors of the current basic block
+ Edge e = l.successors;
+ while (e != null) {
+ Label n = e.successor.getFirst();
+ boolean change = f.merge(cw, n.frame, e.info);
+ if (change && n.next == null) {
+ // if n has changed and is not already in the 'changed'
+ // list, adds it to this list
+ n.next = changed;
+ changed = n;
+ }
+ e = e.next;
+ }
+ }
+ this.maxStack = max;
+
+ // visits all the frames that must be stored in the stack map
+ Label l = labels;
+ while (l != null) {
+ f = l.frame;
+ if ((l.status & Label.STORE) != 0) {
+ visitFrame(f);
+ }
+ if ((l.status & Label.REACHABLE) == 0) {
+ // finds start and end of dead basic block
+ Label k = l.successor;
+ int start = l.position;
+ int end = (k == null ? code.length : k.position) - 1;
+ // if non empty basic block
+ if (end >= start) {
+ // replaces instructions with NOP ... NOP ATHROW
+ for (int i = start; i < end; ++i) {
+ code.data[i] = Opcodes.NOP;
+ }
+ code.data[end] = (byte) Opcodes.ATHROW;
+ // emits a frame for this unreachable block
+ startFrame(start, 0, 1);
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType("java/lang/Throwable");
+ endFrame();
+ }
+ }
+ l = l.successor;
+ }
+ } else if (compute == MAXS) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start;
+ Label h = handler.handler;
+ Label e = handler.end;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = Edge.EXCEPTION;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ if ((l.status & Label.JSR) == 0) {
+ b.next = l.successors;
+ l.successors = b;
+ } else {
+ // if l is a JSR block, adds b after the first two edges
+ // to preserve the hypothesis about JSR block successors
+ // order (see {@link #visitJumpInsn})
+ b.next = l.successors.next.next;
+ l.successors.next.next = b;
+ }
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ if (subroutines > 0) {
+ // completes the control flow graph with the RET successors
+ /*
+ * first step: finds the subroutines. This step determines, for
+ * each basic block, to which subroutine(s) it belongs.
+ */
+ // finds the basic blocks that belong to the "main" subroutine
+ int id = 0;
+ labels.visitSubroutine(null, 1, subroutines);
+ // finds the basic blocks that belong to the real subroutines
+ Label l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ // if this subroutine has not been visited yet...
+ if ((subroutine.status & Label.VISITED) == 0) {
+ // ...assigns it a new id and finds its basic blocks
+ id += 1;
+ subroutine.visitSubroutine(null, (id / 32L) << 32
+ | (1L << (id % 32)), subroutines);
+ }
+ }
+ l = l.successor;
+ }
+ // second step: finds the successors of RET blocks
+ l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ Label L = labels;
+ while (L != null) {
+ L.status &= ~Label.VISITED;
+ L = L.successor;
+ }
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ subroutine.visitSubroutine(l, 0, subroutines);
+ }
+ l = l.successor;
+ }
+ }
+
+ /*
+ * control flow analysis algorithm: while the block stack is not
+ * empty, pop a block from this stack, update the max stack size,
+ * compute the true (non relative) begin stack size of the
+ * successors of this block, and push these successors onto the
+ * stack (unless they have already been pushed onto the stack).
+ * Note: by hypothesis, the {@link Label#inputStackTop} of the
+ * blocks in the block stack are the true (non relative) beginning
+ * stack sizes of these blocks.
+ */
+ int max = 0;
+ Label stack = labels;
+ while (stack != null) {
+ // pops a block from the stack
+ Label l = stack;
+ stack = stack.next;
+ // computes the true (non relative) max stack size of this block
+ int start = l.inputStackTop;
+ int blockMax = start + l.outputStackMax;
+ // updates the global max stack size
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // analyzes the successors of the block
+ Edge b = l.successors;
+ if ((l.status & Label.JSR) != 0) {
+ // ignores the first edge of JSR blocks (virtual successor)
+ b = b.next;
+ }
+ while (b != null) {
+ l = b.successor;
+ // if this successor has not already been pushed...
+ if ((l.status & Label.PUSHED) == 0) {
+ // computes its true beginning stack size...
+ l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start
+ + b.info;
+ // ...and pushes it onto the stack
+ l.status |= Label.PUSHED;
+ l.next = stack;
+ stack = l;
+ }
+ b = b.next;
+ }
+ }
+ this.maxStack = max;
+ } else {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+ }
+
+ public void visitEnd() {
+ }
+
+ /**
+ * Adds a successor to the {@link #currentBlock currentBlock} block.
+ *
+ * @param info information about the control flow edge to be added.
+ * @param successor the successor block to be added to the current block.
+ */
+ private void addSuccessor(final int info, final Label successor) {
+ // creates and initializes an Edge object...
+ Edge b = new Edge();
+ b.info = info;
+ b.successor = successor;
+ // ...and adds it to the successor list of the currentBlock block
+ b.next = currentBlock.successors;
+ currentBlock.successors = b;
+ }
+
+ /**
+ * Ends the current basic block. This method must be used in the case where
+ * the current basic block does not have any successor.
+ */
+ private void noSuccessor() {
+ if (compute == FRAMES) {
+ Label l = new Label();
+ l.frame = new Frame();
+ l.frame.owner = l;
+ l.resolve(this, code.length, code.data);
+ previousBlock.successor = l;
+ previousBlock = l;
+ } else {
+ currentBlock.outputStackMax = maxStackSize;
+ }
+ currentBlock = null;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: dump bytecode array
+ // ------------------------------------------------------------------------
+
+ /**
+ * Visits a frame that has been computed from scratch.
+ *
+ * @param f the frame that must be visited.
+ */
+ private void visitFrame(final Frame f) {
+ int i, t;
+ int nTop = 0;
+ int nLocal = 0;
+ int nStack = 0;
+ int[] locals = f.inputLocals;
+ int[] stacks = f.inputStack;
+ // computes the number of locals (ignores TOP types that are just after
+ // a LONG or a DOUBLE, and all trailing TOP types)
+ for (i = 0; i < locals.length; ++i) {
+ t = locals[i];
+ if (t == Frame.TOP) {
+ ++nTop;
+ } else {
+ nLocal += nTop + 1;
+ nTop = 0;
+ }
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // computes the stack size (ignores TOP types that are just after
+ // a LONG or a DOUBLE)
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ ++nStack;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // visits the frame and its content
+ startFrame(f.owner.position, nLocal, nStack);
+ for (i = 0; nLocal > 0; ++i, --nLocal) {
+ t = locals[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ endFrame();
+ }
+
+ /**
+ * Starts the visit of a stack map frame.
+ *
+ * @param offset the offset of the instruction to which the frame
+ * corresponds.
+ * @param nLocal the number of local variables in the frame.
+ * @param nStack the number of stack elements in the frame.
+ */
+ private void startFrame(final int offset, final int nLocal, final int nStack)
+ {
+ int n = 3 + nLocal + nStack;
+ if (frame == null || frame.length < n) {
+ frame = new int[n];
+ }
+ frame[0] = offset;
+ frame[1] = nLocal;
+ frame[2] = nStack;
+ frameIndex = 3;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks if the visit of the current frame {@link #frame} is finished, and
+ * if yes, write it in the StackMapTable attribute.
+ */
+ private void endFrame() {
+ if (previousFrame != null) { // do not write the first frame
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ }
+ writeFrame();
+ ++frameCount;
+ }
+ previousFrame = frame;
+ frame = null;
+ }
+
+ /**
+ * Compress and writes the current frame {@link #frame} in the StackMapTable
+ * attribute.
+ */
+ private void writeFrame() {
+ int clocalsSize = frame[1];
+ int cstackSize = frame[2];
+ if ((cw.version & 0xFFFF) < Opcodes.V1_6) {
+ stackMap.putShort(frame[0]).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ return;
+ }
+ int localsSize = previousFrame[1];
+ int type = FULL_FRAME;
+ int k = 0;
+ int delta;
+ if (frameCount == 0) {
+ delta = frame[0];
+ } else {
+ delta = frame[0] - previousFrame[0] - 1;
+ }
+ if (cstackSize == 0) {
+ k = clocalsSize - localsSize;
+ switch (k) {
+ case -3:
+ case -2:
+ case -1:
+ type = CHOP_FRAME;
+ localsSize = clocalsSize;
+ break;
+ case 0:
+ type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ type = APPEND_FRAME;
+ break;
+ }
+ } else if (clocalsSize == localsSize && cstackSize == 1) {
+ type = delta < 63
+ ? SAME_LOCALS_1_STACK_ITEM_FRAME
+ : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
+ }
+ if (type != FULL_FRAME) {
+ // verify if locals are the same
+ int l = 3;
+ for (int j = 0; j < localsSize; j++) {
+ if (frame[l] != previousFrame[l]) {
+ type = FULL_FRAME;
+ break;
+ }
+ l++;
+ }
+ }
+ switch (type) {
+ case SAME_FRAME:
+ stackMap.putByte(delta);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_FRAME_EXTENDED:
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ break;
+ case CHOP_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ break;
+ case APPEND_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+ break;
+ // case FULL_FRAME:
+ default:
+ stackMap.putByte(FULL_FRAME)
+ .putShort(delta)
+ .putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ }
+ }
+
+ /**
+ * Writes some types of the current frame {@link #frame} into the
+ * StackMapTableAttribute. This method converts types from the format used
+ * in {@link Label} to the format used in StackMapTable attributes. In
+ * particular, it converts type table indexes to constant pool indexes.
+ *
+ * @param start index of the first type in {@link #frame} to write.
+ * @param end index of last type in {@link #frame} to write (exclusive).
+ */
+ private void writeFrameTypes(final int start, final int end) {
+ for (int i = start; i < end; ++i) {
+ int t = frame[i];
+ int d = t & Frame.DIM;
+ if (d == 0) {
+ int v = t & Frame.BASE_VALUE;
+ switch (t & Frame.BASE_KIND) {
+ case Frame.OBJECT:
+ stackMap.putByte(7)
+ .putShort(cw.newClass(cw.typeTable[v].strVal1));
+ break;
+ case Frame.UNINITIALIZED:
+ stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+ break;
+ default:
+ stackMap.putByte(v);
+ }
+ } else {
+ StringBuffer buf = new StringBuffer();
+ d >>= 28;
+ while (d-- > 0) {
+ buf.append('[');
+ }
+ if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
+ buf.append('L');
+ buf.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
+ buf.append(';');
+ } else {
+ switch (t & 0xF) {
+ case 1:
+ buf.append('I');
+ break;
+ case 2:
+ buf.append('F');
+ break;
+ case 3:
+ buf.append('D');
+ break;
+ case 9:
+ buf.append('Z');
+ break;
+ case 10:
+ buf.append('B');
+ break;
+ case 11:
+ buf.append('C');
+ break;
+ case 12:
+ buf.append('S');
+ break;
+ default:
+ buf.append('J');
+ }
+ }
+ stackMap.putByte(7).putShort(cw.newClass(buf.toString()));
+ }
+ }
+ }
+
+ private void writeFrameType(final Object type) {
+ if (type instanceof String) {
+ stackMap.putByte(7).putShort(cw.newClass((String) type));
+ } else if (type instanceof Integer) {
+ stackMap.putByte(((Integer) type).intValue());
+ } else {
+ stackMap.putByte(8).putShort(((Label) type).position);
+ }
+ }
+
+ /**
+ * Returns the size of the bytecode of this method.
+ *
+ * @return the size of the bytecode of this method.
+ */
+ final int getSize() {
+ if (classReaderOffset != 0) {
+ return 6 + classReaderLength;
+ }
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
+ int size = 8;
+ if (code.length > 0) {
+ cw.newUTF8("Code");
+ size += 18 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ cw.newUTF8("LocalVariableTable");
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ cw.newUTF8("LocalVariableTypeTable");
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ cw.newUTF8("LineNumberTable");
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ cw.newUTF8(zip ? "StackMapTable" : "StackMap");
+ size += 8 + stackMap.length;
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw,
+ code.data,
+ code.length,
+ maxStack,
+ maxLocals);
+ }
+ }
+ if (exceptionCount > 0) {
+ cw.newUTF8("Exceptions");
+ size += 8 + 2 * exceptionCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ cw.newUTF8("Signature");
+ cw.newUTF8(signature);
+ size += 8;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ cw.newUTF8("AnnotationDefault");
+ size += 6 + annd.length;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ cw.newUTF8("RuntimeVisibleParameterAnnotations");
+ size += 7 + 2 * (panns.length - synthetics);
+ for (int i = panns.length - 1; i >= synthetics; --i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ cw.newUTF8("RuntimeInvisibleParameterAnnotations");
+ size += 7 + 2 * (ipanns.length - synthetics);
+ for (int i = ipanns.length - 1; i >= synthetics; --i) {
+ size += ipanns[i] == null ? 0 : ipanns[i].getSize();
+ }
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the bytecode of this method in the given byte vector.
+ *
+ * @param out the byte vector into which the bytecode of this method must be
+ * copied.
+ */
+ final void put(final ByteVector out) {
+ out.putShort(access).putShort(name).putShort(desc);
+ if (classReaderOffset != 0) {
+ out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
+ return;
+ }
+ int attributeCount = 0;
+ if (code.length > 0) {
+ ++attributeCount;
+ }
+ if (exceptionCount > 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (code.length > 0) {
+ int size = 12 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ size += 8 + stackMap.length;
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw,
+ code.data,
+ code.length,
+ maxStack,
+ maxLocals);
+ }
+ out.putShort(cw.newUTF8("Code")).putInt(size);
+ out.putShort(maxStack).putShort(maxLocals);
+ out.putInt(code.length).putByteArray(code.data, 0, code.length);
+ out.putShort(handlerCount);
+ if (handlerCount > 0) {
+ Handler h = firstHandler;
+ while (h != null) {
+ out.putShort(h.start.position)
+ .putShort(h.end.position)
+ .putShort(h.handler.position)
+ .putShort(h.type);
+ h = h.next;
+ }
+ }
+ attributeCount = 0;
+ if (localVar != null) {
+ ++attributeCount;
+ }
+ if (localVarType != null) {
+ ++attributeCount;
+ }
+ if (lineNumber != null) {
+ ++attributeCount;
+ }
+ if (stackMap != null) {
+ ++attributeCount;
+ }
+ if (cattrs != null) {
+ attributeCount += cattrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (localVar != null) {
+ out.putShort(cw.newUTF8("LocalVariableTable"));
+ out.putInt(localVar.length + 2).putShort(localVarCount);
+ out.putByteArray(localVar.data, 0, localVar.length);
+ }
+ if (localVarType != null) {
+ out.putShort(cw.newUTF8("LocalVariableTypeTable"));
+ out.putInt(localVarType.length + 2).putShort(localVarTypeCount);
+ out.putByteArray(localVarType.data, 0, localVarType.length);
+ }
+ if (lineNumber != null) {
+ out.putShort(cw.newUTF8("LineNumberTable"));
+ out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
+ out.putByteArray(lineNumber.data, 0, lineNumber.length);
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));
+ out.putInt(stackMap.length + 2).putShort(frameCount);
+ out.putByteArray(stackMap.data, 0, stackMap.length);
+ }
+ if (cattrs != null) {
+ cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
+ }
+ }
+ if (exceptionCount > 0) {
+ out.putShort(cw.newUTF8("Exceptions"))
+ .putInt(2 * exceptionCount + 2);
+ out.putShort(exceptionCount);
+ for (int i = 0; i < exceptionCount; ++i) {
+ out.putShort(exceptions[i]);
+ }
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0
+ && (cw.version & 0xffff) < Opcodes.V1_5)
+ {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ out.putShort(cw.newUTF8("Signature"))
+ .putInt(2)
+ .putShort(cw.newUTF8(signature));
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ out.putShort(cw.newUTF8("AnnotationDefault"));
+ out.putInt(annd.length);
+ out.putByteArray(annd.data, 0, annd.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
+ AnnotationWriter.put(panns, synthetics, out);
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
+ AnnotationWriter.put(ipanns, synthetics, out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+
+ /**
+ * Resizes and replaces the temporary instructions inserted by
+ * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
+ * and instruction addresses consistent. This may require to resize other
+ * existing instructions, or even to introduce new instructions: for
+ * example, increasing the size of an instruction by 2 at the middle of a
+ * method can increases the offset of an IFEQ instruction from 32766 to
+ * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
+ * 32765. This, in turn, may require to increase the size of another jump
+ * instruction, and so on... All these operations are handled automatically
+ * by this method. <p> <i>This method must be called after all the method
+ * that is being built has been visited</i>. In particular, the
+ * {@link Label Label} objects used to construct the method are no longer
+ * valid after this method has been called.
+ */
+ private void resizeInstructions() {
+ byte[] b = code.data; // bytecode of the method
+ int u, v, label; // indexes in b
+ int i, j; // loop indexes
+ /*
+ * 1st step: As explained above, resizing an instruction may require to
+ * resize another one, which may require to resize yet another one, and
+ * so on. The first step of the algorithm consists in finding all the
+ * instructions that need to be resized, without modifying the code.
+ * This is done by the following "fix point" algorithm:
+ *
+ * Parse the code to find the jump instructions whose offset will need
+ * more than 2 bytes to be stored (the future offset is computed from
+ * the current offset and from the number of bytes that will be inserted
+ * or removed between the source and target instructions). For each such
+ * instruction, adds an entry in (a copy of) the indexes and sizes
+ * arrays (if this has not already been done in a previous iteration!).
+ *
+ * If at least one entry has been added during the previous step, go
+ * back to the beginning, otherwise stop.
+ *
+ * In fact the real algorithm is complicated by the fact that the size
+ * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
+ * position in the bytecode (because of padding). In order to ensure the
+ * convergence of the algorithm, the number of bytes to be added or
+ * removed from these instructions is over estimated during the previous
+ * loop, and computed exactly only after the loop is finished (this
+ * requires another pass to parse the bytecode of the method).
+ */
+ int[] allIndexes = new int[0]; // copy of indexes
+ int[] allSizes = new int[0]; // copy of sizes
+ boolean[] resize; // instructions to be resized
+ int newOffset; // future offset of a jump instruction
+
+ resize = new boolean[code.length];
+
+ // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
+ int state = 3;
+ do {
+ if (state == 3) {
+ state = 2;
+ }
+ u = 0;
+ while (u < b.length) {
+ int opcode = b[u] & 0xFF; // opcode of current instruction
+ int insert = 0; // bytes to be added after this instruction
+
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // converts temporary opcodes 202 to 217, 218 and
+ // 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (newOffset < Short.MIN_VALUE
+ || newOffset > Short.MAX_VALUE)
+ {
+ if (!resize[u]) {
+ if (opcode == Opcodes.GOTO
+ || opcode == Opcodes.JSR)
+ {
+ // two additional bytes will be required to
+ // replace this GOTO or JSR instruction with
+ // a GOTO_W or a JSR_W
+ insert = 2;
+ } else {
+ // five additional bytes will be required to
+ // replace this IFxxx <l> instruction with
+ // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+ // is the "opposite" opcode of IFxxx (i.e.,
+ // IFNE for IFEQ) and where <l'> designates
+ // the instruction just after the GOTO_W.
+ insert = 5;
+ }
+ resize[u] = true;
+ }
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ if (state == 1) {
+ // true number of bytes to be added (or removed)
+ // from this instruction = (future number of padding
+ // bytes - current number of padding byte) -
+ // previously over estimated variation =
+ // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+ // = (-newOffset%4 + u%4) - u%4
+ // = -(newOffset & 3)
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // over estimation of the number of bytes to be
+ // added to this instruction = 3 - current number
+ // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ if (state == 1) {
+ // like TABL_INSN
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // like TABL_INSN
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 8 * readInt(b, u + 4) + 8;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ u += 5;
+ break;
+ // case ClassWriter.MANA_INSN:
+ default:
+ u += 4;
+ break;
+ }
+ if (insert != 0) {
+ // adds a new (u, insert) entry in the allIndexes and
+ // allSizes arrays
+ int[] newIndexes = new int[allIndexes.length + 1];
+ int[] newSizes = new int[allSizes.length + 1];
+ System.arraycopy(allIndexes,
+ 0,
+ newIndexes,
+ 0,
+ allIndexes.length);
+ System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+ newIndexes[allIndexes.length] = u;
+ newSizes[allSizes.length] = insert;
+ allIndexes = newIndexes;
+ allSizes = newSizes;
+ if (insert > 0) {
+ state = 3;
+ }
+ }
+ }
+ if (state < 3) {
+ --state;
+ }
+ } while (state != 0);
+
+ // 2nd step:
+ // copies the bytecode of the method into a new bytevector, updates the
+ // offsets, and inserts (or removes) bytes as requested.
+
+ ByteVector newCode = new ByteVector(code.length);
+
+ u = 0;
+ while (u < code.length) {
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ newCode.putByte(opcode);
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (resize[u]) {
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where <l'> designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO) {
+ newCode.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ newCode.putByte(201); // JSR_W
+ } else {
+ newCode.putByte(opcode <= 166
+ ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ newCode.putShort(8); // jump offset
+ newCode.putByte(200); // GOTO_W
+ // newOffset now computed from start of GOTO_W
+ newOffset -= 3;
+ }
+ newCode.putInt(newOffset);
+ } else {
+ newCode.putByte(opcode);
+ newCode.putShort(newOffset);
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ label = u + readInt(b, u + 1);
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ newCode.putByte(opcode);
+ newCode.putInt(newOffset);
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.TABLESWITCH);
+ newCode.length += (4 - newCode.length % 4) % 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ j = readInt(b, u) - j + 1;
+ u += 4;
+ newCode.putInt(readInt(b, u - 4));
+ for (; j > 0; --j) {
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.LOOKUPSWITCH);
+ newCode.length += (4 - newCode.length % 4) % 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ for (; j > 0; --j) {
+ newCode.putInt(readInt(b, u));
+ u += 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ newCode.putByteArray(b, u, 6);
+ u += 6;
+ } else {
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ newCode.putByteArray(b, u, 2);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ newCode.putByteArray(b, u, 3);
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ newCode.putByteArray(b, u, 5);
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ break;
+ }
+ }
+
+ // recomputes the stack map frames
+ if (frameCount > 0) {
+ if (compute == FRAMES) {
+ frameCount = 0;
+ stackMap = null;
+ previousFrame = null;
+ frame = null;
+ Frame f = new Frame();
+ f.owner = labels;
+ Type[] args = Type.getArgumentTypes(descriptor);
+ f.initInputFrame(cw, access, args, maxLocals);
+ visitFrame(f);
+ Label l = labels;
+ while (l != null) {
+ /*
+ * here we need the original label position. getNewOffset
+ * must therefore never have been called for this label.
+ */
+ u = l.position - 3;
+ if ((l.status & Label.STORE) != 0 || (u >= 0 && resize[u]))
+ {
+ getNewOffset(allIndexes, allSizes, l);
+ // TODO update offsets in UNINITIALIZED values
+ visitFrame(l.frame);
+ }
+ l = l.successor;
+ }
+ } else {
+ /*
+ * Resizing an existing stack map frame table is really hard.
+ * Not only the table must be parsed to update the offets, but
+ * new frames may be needed for jump instructions that were
+ * inserted by this method. And updating the offsets or
+ * inserting frames can change the format of the following
+ * frames, in case of packed frames. In practice the whole table
+ * must be recomputed. For this the frames are marked as
+ * potentially invalid. This will cause the whole class to be
+ * reread and rewritten with the COMPUTE_FRAMES option (see the
+ * ClassWriter.toByteArray method). This is not very efficient
+ * but is much easier and requires much less code than any other
+ * method I can think of.
+ */
+ cw.invalidFrames = true;
+ }
+ }
+ // updates the exception handler block labels
+ Handler h = firstHandler;
+ while (h != null) {
+ getNewOffset(allIndexes, allSizes, h.start);
+ getNewOffset(allIndexes, allSizes, h.end);
+ getNewOffset(allIndexes, allSizes, h.handler);
+ h = h.next;
+ }
+ // updates the instructions addresses in the
+ // local var and line number tables
+ for (i = 0; i < 2; ++i) {
+ ByteVector bv = i == 0 ? localVar : localVarType;
+ if (bv != null) {
+ b = bv.data;
+ u = 0;
+ while (u < bv.length) {
+ label = readUnsignedShort(b, u);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label);
+ writeShort(b, u, newOffset);
+ label += readUnsignedShort(b, u + 2);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label)
+ - newOffset;
+ writeShort(b, u + 2, newOffset);
+ u += 10;
+ }
+ }
+ }
+ if (lineNumber != null) {
+ b = lineNumber.data;
+ u = 0;
+ while (u < lineNumber.length) {
+ writeShort(b, u, getNewOffset(allIndexes,
+ allSizes,
+ 0,
+ readUnsignedShort(b, u)));
+ u += 4;
+ }
+ }
+ // updates the labels of the other attributes
+ Attribute attr = cattrs;
+ while (attr != null) {
+ Label[] labels = attr.getLabels();
+ if (labels != null) {
+ for (i = labels.length - 1; i >= 0; --i) {
+ getNewOffset(allIndexes, allSizes, labels[i]);
+ }
+ }
+ attr = attr.next;
+ }
+
+ // replaces old bytecodes with new ones
+ code = newCode;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Opcodes.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Opcodes.java
new file mode 100644
index 0000000..aa93ec9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Opcodes.java
@@ -0,0 +1,341 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+/**
+ * Defines the JVM opcodes, access flags and array type codes. This interface
+ * does not define all the JVM opcodes because some opcodes are automatically
+ * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
+ * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
+ * opcodes are therefore not defined in this interface. Likewise for LDC,
+ * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
+ * JSR_W.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface Opcodes {
+
+ // versions
+
+ int V1_1 = 3 << 16 | 45;
+ int V1_2 = 0 << 16 | 46;
+ int V1_3 = 0 << 16 | 47;
+ int V1_4 = 0 << 16 | 48;
+ int V1_5 = 0 << 16 | 49;
+ int V1_6 = 0 << 16 | 50;
+
+ // access flags
+
+ int ACC_PUBLIC = 0x0001; // class, field, method
+ int ACC_PRIVATE = 0x0002; // class, field, method
+ int ACC_PROTECTED = 0x0004; // class, field, method
+ int ACC_STATIC = 0x0008; // field, method
+ int ACC_FINAL = 0x0010; // class, field, method
+ int ACC_SUPER = 0x0020; // class
+ int ACC_SYNCHRONIZED = 0x0020; // method
+ int ACC_VOLATILE = 0x0040; // field
+ int ACC_BRIDGE = 0x0040; // method
+ int ACC_VARARGS = 0x0080; // method
+ int ACC_TRANSIENT = 0x0080; // field
+ int ACC_NATIVE = 0x0100; // method
+ int ACC_INTERFACE = 0x0200; // class
+ int ACC_ABSTRACT = 0x0400; // class, method
+ int ACC_STRICT = 0x0800; // method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method
+ int ACC_ANNOTATION = 0x2000; // class
+ int ACC_ENUM = 0x4000; // class(?) field inner
+
+ // ASM specific pseudo access flags
+
+ int ACC_DEPRECATED = 131072; // class, field, method
+
+ // types for NEWARRAY
+
+ int T_BOOLEAN = 4;
+ int T_CHAR = 5;
+ int T_FLOAT = 6;
+ int T_DOUBLE = 7;
+ int T_BYTE = 8;
+ int T_SHORT = 9;
+ int T_INT = 10;
+ int T_LONG = 11;
+
+ // stack map frame types
+
+ /**
+ * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
+ */
+ int F_NEW = -1;
+
+ /**
+ * Represents a compressed frame with complete frame data.
+ */
+ int F_FULL = 0;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that additional 1-3 locals are defined, and
+ * with an empty stack.
+ */
+ int F_APPEND = 1;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that the last 1-3 locals are absent and with
+ * an empty stack.
+ */
+ int F_CHOP = 2;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with an empty stack.
+ */
+ int F_SAME = 3;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with a single value on the stack.
+ */
+ int F_SAME1 = 4;
+
+ Integer TOP = new Integer(0);
+ Integer INTEGER = new Integer(1);
+ Integer FLOAT = new Integer(2);
+ Integer DOUBLE = new Integer(3);
+ Integer LONG = new Integer(4);
+ Integer NULL = new Integer(5);
+ Integer UNINITIALIZED_THIS = new Integer(6);
+
+ // opcodes // visit method (- = idem)
+
+ int NOP = 0; // visitInsn
+ int ACONST_NULL = 1; // -
+ int ICONST_M1 = 2; // -
+ int ICONST_0 = 3; // -
+ int ICONST_1 = 4; // -
+ int ICONST_2 = 5; // -
+ int ICONST_3 = 6; // -
+ int ICONST_4 = 7; // -
+ int ICONST_5 = 8; // -
+ int LCONST_0 = 9; // -
+ int LCONST_1 = 10; // -
+ int FCONST_0 = 11; // -
+ int FCONST_1 = 12; // -
+ int FCONST_2 = 13; // -
+ int DCONST_0 = 14; // -
+ int DCONST_1 = 15; // -
+ int BIPUSH = 16; // visitIntInsn
+ int SIPUSH = 17; // -
+ int LDC = 18; // visitLdcInsn
+ // int LDC_W = 19; // -
+ // int LDC2_W = 20; // -
+ int ILOAD = 21; // visitVarInsn
+ int LLOAD = 22; // -
+ int FLOAD = 23; // -
+ int DLOAD = 24; // -
+ int ALOAD = 25; // -
+ // int ILOAD_0 = 26; // -
+ // int ILOAD_1 = 27; // -
+ // int ILOAD_2 = 28; // -
+ // int ILOAD_3 = 29; // -
+ // int LLOAD_0 = 30; // -
+ // int LLOAD_1 = 31; // -
+ // int LLOAD_2 = 32; // -
+ // int LLOAD_3 = 33; // -
+ // int FLOAD_0 = 34; // -
+ // int FLOAD_1 = 35; // -
+ // int FLOAD_2 = 36; // -
+ // int FLOAD_3 = 37; // -
+ // int DLOAD_0 = 38; // -
+ // int DLOAD_1 = 39; // -
+ // int DLOAD_2 = 40; // -
+ // int DLOAD_3 = 41; // -
+ // int ALOAD_0 = 42; // -
+ // int ALOAD_1 = 43; // -
+ // int ALOAD_2 = 44; // -
+ // int ALOAD_3 = 45; // -
+ int IALOAD = 46; // visitInsn
+ int LALOAD = 47; // -
+ int FALOAD = 48; // -
+ int DALOAD = 49; // -
+ int AALOAD = 50; // -
+ int BALOAD = 51; // -
+ int CALOAD = 52; // -
+ int SALOAD = 53; // -
+ int ISTORE = 54; // visitVarInsn
+ int LSTORE = 55; // -
+ int FSTORE = 56; // -
+ int DSTORE = 57; // -
+ int ASTORE = 58; // -
+ // int ISTORE_0 = 59; // -
+ // int ISTORE_1 = 60; // -
+ // int ISTORE_2 = 61; // -
+ // int ISTORE_3 = 62; // -
+ // int LSTORE_0 = 63; // -
+ // int LSTORE_1 = 64; // -
+ // int LSTORE_2 = 65; // -
+ // int LSTORE_3 = 66; // -
+ // int FSTORE_0 = 67; // -
+ // int FSTORE_1 = 68; // -
+ // int FSTORE_2 = 69; // -
+ // int FSTORE_3 = 70; // -
+ // int DSTORE_0 = 71; // -
+ // int DSTORE_1 = 72; // -
+ // int DSTORE_2 = 73; // -
+ // int DSTORE_3 = 74; // -
+ // int ASTORE_0 = 75; // -
+ // int ASTORE_1 = 76; // -
+ // int ASTORE_2 = 77; // -
+ // int ASTORE_3 = 78; // -
+ int IASTORE = 79; // visitInsn
+ int LASTORE = 80; // -
+ int FASTORE = 81; // -
+ int DASTORE = 82; // -
+ int AASTORE = 83; // -
+ int BASTORE = 84; // -
+ int CASTORE = 85; // -
+ int SASTORE = 86; // -
+ int POP = 87; // -
+ int POP2 = 88; // -
+ int DUP = 89; // -
+ int DUP_X1 = 90; // -
+ int DUP_X2 = 91; // -
+ int DUP2 = 92; // -
+ int DUP2_X1 = 93; // -
+ int DUP2_X2 = 94; // -
+ int SWAP = 95; // -
+ int IADD = 96; // -
+ int LADD = 97; // -
+ int FADD = 98; // -
+ int DADD = 99; // -
+ int ISUB = 100; // -
+ int LSUB = 101; // -
+ int FSUB = 102; // -
+ int DSUB = 103; // -
+ int IMUL = 104; // -
+ int LMUL = 105; // -
+ int FMUL = 106; // -
+ int DMUL = 107; // -
+ int IDIV = 108; // -
+ int LDIV = 109; // -
+ int FDIV = 110; // -
+ int DDIV = 111; // -
+ int IREM = 112; // -
+ int LREM = 113; // -
+ int FREM = 114; // -
+ int DREM = 115; // -
+ int INEG = 116; // -
+ int LNEG = 117; // -
+ int FNEG = 118; // -
+ int DNEG = 119; // -
+ int ISHL = 120; // -
+ int LSHL = 121; // -
+ int ISHR = 122; // -
+ int LSHR = 123; // -
+ int IUSHR = 124; // -
+ int LUSHR = 125; // -
+ int IAND = 126; // -
+ int LAND = 127; // -
+ int IOR = 128; // -
+ int LOR = 129; // -
+ int IXOR = 130; // -
+ int LXOR = 131; // -
+ int IINC = 132; // visitIincInsn
+ int I2L = 133; // visitInsn
+ int I2F = 134; // -
+ int I2D = 135; // -
+ int L2I = 136; // -
+ int L2F = 137; // -
+ int L2D = 138; // -
+ int F2I = 139; // -
+ int F2L = 140; // -
+ int F2D = 141; // -
+ int D2I = 142; // -
+ int D2L = 143; // -
+ int D2F = 144; // -
+ int I2B = 145; // -
+ int I2C = 146; // -
+ int I2S = 147; // -
+ int LCMP = 148; // -
+ int FCMPL = 149; // -
+ int FCMPG = 150; // -
+ int DCMPL = 151; // -
+ int DCMPG = 152; // -
+ int IFEQ = 153; // visitJumpInsn
+ int IFNE = 154; // -
+ int IFLT = 155; // -
+ int IFGE = 156; // -
+ int IFGT = 157; // -
+ int IFLE = 158; // -
+ int IF_ICMPEQ = 159; // -
+ int IF_ICMPNE = 160; // -
+ int IF_ICMPLT = 161; // -
+ int IF_ICMPGE = 162; // -
+ int IF_ICMPGT = 163; // -
+ int IF_ICMPLE = 164; // -
+ int IF_ACMPEQ = 165; // -
+ int IF_ACMPNE = 166; // -
+ int GOTO = 167; // -
+ int JSR = 168; // -
+ int RET = 169; // visitVarInsn
+ int TABLESWITCH = 170; // visiTableSwitchInsn
+ int LOOKUPSWITCH = 171; // visitLookupSwitch
+ int IRETURN = 172; // visitInsn
+ int LRETURN = 173; // -
+ int FRETURN = 174; // -
+ int DRETURN = 175; // -
+ int ARETURN = 176; // -
+ int RETURN = 177; // -
+ int GETSTATIC = 178; // visitFieldInsn
+ int PUTSTATIC = 179; // -
+ int GETFIELD = 180; // -
+ int PUTFIELD = 181; // -
+ int INVOKEVIRTUAL = 182; // visitMethodInsn
+ int INVOKESPECIAL = 183; // -
+ int INVOKESTATIC = 184; // -
+ int INVOKEINTERFACE = 185; // -
+ // int UNUSED = 186; // NOT VISITED
+ int NEW = 187; // visitTypeInsn
+ int NEWARRAY = 188; // visitIntInsn
+ int ANEWARRAY = 189; // visitTypeInsn
+ int ARRAYLENGTH = 190; // visitInsn
+ int ATHROW = 191; // -
+ int CHECKCAST = 192; // visitTypeInsn
+ int INSTANCEOF = 193; // -
+ int MONITORENTER = 194; // visitInsn
+ int MONITOREXIT = 195; // -
+ // int WIDE = 196; // NOT VISITED
+ int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
+ int IFNULL = 198; // visitJumpInsn
+ int IFNONNULL = 199; // -
+ // int GOTO_W = 200; // -
+ // int JSR_W = 201; // -
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Type.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Type.java
new file mode 100644
index 0000000..2b60ac3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/Type.java
@@ -0,0 +1,794 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * A Java type. This class can be used to make it easier to manipulate type and
+ * method descriptors.
+ *
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type {
+
+ /**
+ * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int VOID = 0;
+
+ /**
+ * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BOOLEAN = 1;
+
+ /**
+ * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int CHAR = 2;
+
+ /**
+ * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BYTE = 3;
+
+ /**
+ * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int SHORT = 4;
+
+ /**
+ * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int INT = 5;
+
+ /**
+ * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int FLOAT = 6;
+
+ /**
+ * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int LONG = 7;
+
+ /**
+ * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int DOUBLE = 8;
+
+ /**
+ * The sort of array reference types. See {@link #getSort getSort}.
+ */
+ public static final int ARRAY = 9;
+
+ /**
+ * The sort of object reference type. See {@link #getSort getSort}.
+ */
+ public static final int OBJECT = 10;
+
+ /**
+ * The <tt>void</tt> type.
+ */
+ public static final Type VOID_TYPE = new Type(VOID);
+
+ /**
+ * The <tt>boolean</tt> type.
+ */
+ public static final Type BOOLEAN_TYPE = new Type(BOOLEAN);
+
+ /**
+ * The <tt>char</tt> type.
+ */
+ public static final Type CHAR_TYPE = new Type(CHAR);
+
+ /**
+ * The <tt>byte</tt> type.
+ */
+ public static final Type BYTE_TYPE = new Type(BYTE);
+
+ /**
+ * The <tt>short</tt> type.
+ */
+ public static final Type SHORT_TYPE = new Type(SHORT);
+
+ /**
+ * The <tt>int</tt> type.
+ */
+ public static final Type INT_TYPE = new Type(INT);
+
+ /**
+ * The <tt>float</tt> type.
+ */
+ public static final Type FLOAT_TYPE = new Type(FLOAT);
+
+ /**
+ * The <tt>long</tt> type.
+ */
+ public static final Type LONG_TYPE = new Type(LONG);
+
+ /**
+ * The <tt>double</tt> type.
+ */
+ public static final Type DOUBLE_TYPE = new Type(DOUBLE);
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * The sort of this Java type.
+ */
+ private final int sort;
+
+ /**
+ * A buffer containing the internal name of this Java type. This field is
+ * only used for reference types.
+ */
+ private final char[] buf;
+
+ /**
+ * The offset of the internal name of this Java type in {@link #buf buf}.
+ * This field is only used for reference types.
+ */
+ private final int off;
+
+ /**
+ * The length of the internal name of this Java type. This field is only
+ * used for reference types.
+ */
+ private final int len;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a primitive type.
+ *
+ * @param sort the sort of the primitive type to be constructed.
+ */
+ private Type(final int sort) {
+ this(sort, null, 0, 1);
+ }
+
+ /**
+ * Constructs a reference type.
+ *
+ * @param sort the sort of the reference type to be constructed.
+ * @param buf a buffer containing the descriptor of the previous type.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @param len the length of this descriptor.
+ */
+ private Type(final int sort, final char[] buf, final int off, final int len)
+ {
+ this.sort = sort;
+ this.buf = buf;
+ this.off = off;
+ this.len = len;
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor a type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ public static Type getType(final String typeDescriptor) {
+ return getType(typeDescriptor.toCharArray(), 0);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given internal name.
+ *
+ * @param internalName an internal name.
+ * @return the Java type corresponding to the given internal name.
+ */
+ public static Type getObjectType(final String internalName) {
+ char[] buf = internalName.toCharArray();
+ return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given class.
+ *
+ * @param c a class.
+ * @return the Java type corresponding to the given class.
+ */
+ public static Type getType(final Class c) {
+ if (c.isPrimitive()) {
+ if (c == Integer.TYPE) {
+ return INT_TYPE;
+ } else if (c == Void.TYPE) {
+ return VOID_TYPE;
+ } else if (c == Boolean.TYPE) {
+ return BOOLEAN_TYPE;
+ } else if (c == Byte.TYPE) {
+ return BYTE_TYPE;
+ } else if (c == Character.TYPE) {
+ return CHAR_TYPE;
+ } else if (c == Short.TYPE) {
+ return SHORT_TYPE;
+ } else if (c == Double.TYPE) {
+ return DOUBLE_TYPE;
+ } else if (c == Float.TYPE) {
+ return FLOAT_TYPE;
+ } else /* if (c == Long.TYPE) */{
+ return LONG_TYPE;
+ }
+ } else {
+ return getType(getDescriptor(c));
+ }
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java types corresponding to the argument types of the given
+ * method descriptor.
+ */
+ public static Type[] getArgumentTypes(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ int off = 1;
+ int size = 0;
+ while (true) {
+ char car = buf[off++];
+ if (car == ')') {
+ break;
+ } else if (car == 'L') {
+ while (buf[off++] != ';') {
+ }
+ ++size;
+ } else if (car != '[') {
+ ++size;
+ }
+ }
+ Type[] args = new Type[size];
+ off = 1;
+ size = 0;
+ while (buf[off] != ')') {
+ args[size] = getType(buf, off);
+ off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
+ size += 1;
+ }
+ return args;
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java types corresponding to the argument types of the given
+ * method.
+ */
+ public static Type[] getArgumentTypes(final Method method) {
+ Class[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for (int i = classes.length - 1; i >= 0; --i) {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor a method descriptor.
+ * @return the Java type corresponding to the return type of the given
+ * method descriptor.
+ */
+ public static Type getReturnType(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ return getType(buf, methodDescriptor.indexOf(')') + 1);
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method.
+ *
+ * @param method a method.
+ * @return the Java type corresponding to the return type of the given
+ * method.
+ */
+ public static Type getReturnType(final Method method) {
+ return getType(method.getReturnType());
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param buf a buffer containing a type descriptor.
+ * @param off the offset of this descriptor in the previous buffer.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ private static Type getType(final char[] buf, final int off) {
+ int len;
+ switch (buf[off]) {
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ len = 1;
+ while (buf[off + len] == '[') {
+ ++len;
+ }
+ if (buf[off + len] == 'L') {
+ ++len;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ // case 'L':
+ default:
+ len = 1;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off + 1, len - 1);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the descriptor corresponding to the given argument and return
+ * types.
+ *
+ * @param returnType the return type of the method.
+ * @param argumentTypes the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return
+ * types.
+ */
+ public static String getMethodDescriptor(
+ final Type returnType,
+ final Type[] argumentTypes)
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < argumentTypes.length; ++i) {
+ argumentTypes[i].getDescriptor(buf);
+ }
+ buf.append(')');
+ returnType.getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the internal name of the given class. The internal name of a
+ * class is its fully qualified name, as returned by Class.getName(), where
+ * '.' are replaced by '/'.
+ *
+ * @param c an object or array class.
+ * @return the internal name of the given class.
+ */
+ public static String getInternalName(final Class c) {
+ return c.getName().replace('.', '/');
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given Java type.
+ *
+ * @param c an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+ public static String getDescriptor(final Class c) {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf, c);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param c a {@link Constructor Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+ public static String getConstructorDescriptor(final Constructor c) {
+ Class[] parameters = c.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ return buf.append(")V").toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param m a {@link Method Method} object.
+ * @return the descriptor of the given method.
+ */
+ public static String getMethodDescriptor(final Method m) {
+ Class[] parameters = m.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, m.getReturnType());
+ return buf.toString();
+ }
+
+ // ------------------------------------------------------------------------
+ // Conversion to type descriptors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Appends the descriptor of the given class to the given string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ * @param c the class whose descriptor must be computed.
+ */
+ private static void getDescriptor(final StringBuffer buf, final Class c) {
+ Class d = c;
+ while (true) {
+ if (d.isPrimitive()) {
+ char car;
+ if (d == Integer.TYPE) {
+ car = 'I';
+ } else if (d == Void.TYPE) {
+ car = 'V';
+ } else if (d == Boolean.TYPE) {
+ car = 'Z';
+ } else if (d == Byte.TYPE) {
+ car = 'B';
+ } else if (d == Character.TYPE) {
+ car = 'C';
+ } else if (d == Short.TYPE) {
+ car = 'S';
+ } else if (d == Double.TYPE) {
+ car = 'D';
+ } else if (d == Float.TYPE) {
+ car = 'F';
+ } else /* if (d == Long.TYPE) */{
+ car = 'J';
+ }
+ buf.append(car);
+ return;
+ } else if (d.isArray()) {
+ buf.append('[');
+ d = d.getComponentType();
+ } else {
+ buf.append('L');
+ String name = d.getName();
+ int len = name.length();
+ for (int i = 0; i < len; ++i) {
+ char car = name.charAt(i);
+ buf.append(car == '.' ? '/' : car);
+ }
+ buf.append(';');
+ return;
+ }
+ }
+ }
+
+ /**
+ * Returns the sort of this Java type.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN},
+ * {@link #CHAR CHAR}, {@link #BYTE BYTE}, {@link #SHORT SHORT},
+ * {@link #INT INT}, {@link #FLOAT FLOAT}, {@link #LONG LONG},
+ * {@link #DOUBLE DOUBLE}, {@link #ARRAY ARRAY} or
+ * {@link #OBJECT OBJECT}.
+ */
+ public int getSort() {
+ return sort;
+ }
+
+ /**
+ * Returns the number of dimensions of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+ public int getDimensions() {
+ int i = 1;
+ while (buf[off + i] == '[') {
+ ++i;
+ }
+ return i;
+ }
+
+ // ------------------------------------------------------------------------
+ // Direct conversion from classes to type descriptors,
+ // without intermediate Type objects
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the type of the elements of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+ public Type getElementType() {
+ return getType(buf, off + getDimensions());
+ }
+
+ /**
+ * Returns the name of the class corresponding to this type.
+ *
+ * @return the fully qualified name of the class corresponding to this type.
+ */
+ public String getClassName() {
+ switch (sort) {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuffer b = new StringBuffer(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ b.append("[]");
+ }
+ return b.toString();
+ // case OBJECT:
+ default:
+ return new String(buf, off, len).replace('/', '.');
+ }
+ }
+
+ /**
+ * Returns the internal name of the class corresponding to this object or
+ * array type. The internal name of a class is its fully qualified name (as
+ * returned by Class.getName(), where '.' are replaced by '/'. This method
+ * should only be used for an object or array type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+ public String getInternalName() {
+ return new String(buf, off, len);
+ }
+
+ /**
+ * Returns the descriptor corresponding to this Java type.
+ *
+ * @return the descriptor corresponding to this Java type.
+ */
+ public String getDescriptor() {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Appends the descriptor corresponding to this Java type to the given
+ * string buffer.
+ *
+ * @param buf the string buffer to which the descriptor must be appended.
+ */
+ private void getDescriptor(final StringBuffer buf) {
+ switch (sort) {
+ case VOID:
+ buf.append('V');
+ return;
+ case BOOLEAN:
+ buf.append('Z');
+ return;
+ case CHAR:
+ buf.append('C');
+ return;
+ case BYTE:
+ buf.append('B');
+ return;
+ case SHORT:
+ buf.append('S');
+ return;
+ case INT:
+ buf.append('I');
+ return;
+ case FLOAT:
+ buf.append('F');
+ return;
+ case LONG:
+ buf.append('J');
+ return;
+ case DOUBLE:
+ buf.append('D');
+ return;
+ case ARRAY:
+ buf.append(this.buf, off, len);
+ return;
+ // case OBJECT:
+ default:
+ buf.append('L');
+ buf.append(this.buf, off, len);
+ buf.append(';');
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Corresponding size and opcodes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of values of this type.
+ *
+ * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+ * <tt>double</tt>, and 1 otherwise.
+ */
+ public int getSize() {
+ return sort == LONG || sort == DOUBLE ? 2 : 1;
+ }
+
+ /**
+ * Returns a JVM instruction opcode adapted to this Java type.
+ *
+ * @param opcode a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG, ISHL,
+ * ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to
+ * this Java type. For example, if this type is <tt>float</tt> and
+ * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+ */
+ public int getOpcode(final int opcode) {
+ if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
+ switch (sort) {
+ case BOOLEAN:
+ case BYTE:
+ return opcode + 5;
+ case CHAR:
+ return opcode + 6;
+ case SHORT:
+ return opcode + 7;
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ } else {
+ switch (sort) {
+ case VOID:
+ return opcode + 5;
+ case BOOLEAN:
+ case CHAR:
+ case BYTE:
+ case SHORT:
+ case INT:
+ return opcode;
+ case FLOAT:
+ return opcode + 2;
+ case LONG:
+ return opcode + 1;
+ case DOUBLE:
+ return opcode + 3;
+ // case ARRAY:
+ // case OBJECT:
+ default:
+ return opcode + 4;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Equals, hashCode and toString
+ // ------------------------------------------------------------------------
+
+ /**
+ * Tests if the given object is equal to this type.
+ *
+ * @param o the object to be compared to this type.
+ * @return <tt>true</tt> if the given object is equal to this type.
+ */
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Type)) {
+ return false;
+ }
+ Type t = (Type) o;
+ if (sort != t.sort) {
+ return false;
+ }
+ if (sort == OBJECT || sort == ARRAY) {
+ if (len != t.len) {
+ return false;
+ }
+ for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
+ if (buf[i] != t.buf[j]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+ public int hashCode() {
+ int hc = 13 * sort;
+ if (sort == OBJECT || sort == ARRAY) {
+ for (int i = off, end = i + len; i < end; i++) {
+ hc = 17 * (hc + buf[i]);
+ }
+ }
+ return hc;
+ }
+
+ /**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+ public String toString() {
+ return getDescriptor();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/package.html
new file mode 100644
index 0000000..ea6896c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/package.html
@@ -0,0 +1,117 @@
+<!--
+ ~ ASM: a very small and fast Java bytecode manipulation framework
+ ~ Copyright (c) 2000-2007 INRIA, France Telecom
+ ~ All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions
+ ~ are met:
+ ~ 1. Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ 2. Redistributions in binary form must reproduce the above copyright
+ ~ notice, this list of conditions and the following disclaimer in the
+ ~ documentation and/or other materials provided with the distribution.
+ ~ 3. Neither the name of the copyright holders nor the names of its
+ ~ contributors may be used to endorse or promote products derived from
+ ~ this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ~ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ~ THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides a small and fast bytecode manipulation framework.
+
+<p>
+The <a href="http://www.objectweb.org/asm">ASM</a> framework is organized
+around the {@link org.objectweb.asm.ClassVisitor ClassVisitor},
+{@link org.objectweb.asm.FieldVisitor FieldVisitor} and
+{@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces, which allow
+one to visit the fields and methods of a class, including the bytecode
+instructions of each method.
+
+<p>
+In addition to these main interfaces, ASM provides a {@link
+org.objectweb.asm.ClassReader ClassReader} class, that can parse an
+existing class and make a given visitor visit it. ASM also provides
+a {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is
+a visitor that generates Java class files.
+
+<p>
+In order to generate a class from scratch, only the {@link
+org.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,
+in order to generate a class, one must just call its visit<i>XXX</i>
+methods with the appropriate arguments to generate the desired fields
+and methods. See the "helloworld" example in the ASM distribution for
+more details about class generation.
+
+<p>
+In order to modify existing classes, one must use a {@link
+org.objectweb.asm.ClassReader ClassReader} class to analyze
+the original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter
+ClassWriter} to construct the modified class. The class modifier
+is just a {@link org.objectweb.asm.ClassVisitor ClassVisitor}
+that delegates most of the work to another {@link org.objectweb.asm.ClassVisitor
+ClassVisitor}, but that sometimes changes some parameter values,
+or call additional methods, in order to implement the desired
+modification process. In order to make it easier to implement such
+class modifiers, ASM provides the {@link org.objectweb.asm.ClassAdapter
+ClassAdapter} and {@link org.objectweb.asm.MethodAdapter MethodAdapter}
+classes, which implement the {@link org.objectweb.asm.ClassVisitor ClassVisitor}
+and {@link org.objectweb.asm.MethodVisitor MethodVisitor} interfaces by
+delegating all work to other visitors. See the "adapt" example in the ASM
+distribution for more details about class modification.
+
+<p>
+The size of the core ASM library, <tt>asm.jar</tt>, is only 42KB, which is much
+smaller than the size of the
+<a href="http://jakarta.apache.org/bcel">BCEL</a> library (504KB), and than the
+size of the
+<a href="http://serp.sourceforge.net">SERP</a> library (150KB). ASM is also
+much faster than these tools. Indeed the overhead of a load time class
+transformation process is of the order of 60% with ASM, 700% or more with BCEL,
+and 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM
+distribution)!
+
+ at since ASM 1.3
+</body>
+</html>
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureReader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureReader.java
new file mode 100644
index 0000000..97e3b0c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureReader.java
@@ -0,0 +1,229 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.signature;
+
+/**
+ * A type signature parser to make a signature visitor visit an existing
+ * signature.
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureReader {
+
+ /**
+ * The signature to be read.
+ */
+ private final String signature;
+
+ /**
+ * Constructs a {@link SignatureReader} for the given signature.
+ *
+ * @param signature A <i>ClassSignature</i>, <i>MethodTypeSignature</i>,
+ * or <i>FieldTypeSignature</i>.
+ */
+ public SignatureReader(final String signature) {
+ this.signature = signature;
+ }
+
+ /**
+ * Parses a field type signature and makes the given visitor visit it.
+ *
+ * @param signature a string containing the signature that must be parsed.
+ * @param pos index of the first character of the signature to parsed.
+ * @param v the visitor that must visit this signature.
+ * @return the index of the first character after the parsed signature.
+ */
+ private static int parseType(
+ final String signature,
+ int pos,
+ final SignatureVisitor v)
+ {
+ char c;
+ int start, end;
+ boolean visited, inner;
+ String name;
+
+ switch (c = signature.charAt(pos++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ case 'V':
+ v.visitBaseType(c);
+ return pos;
+
+ case '[':
+ return parseType(signature, pos, v.visitArrayType());
+
+ case 'T':
+ end = signature.indexOf(';', pos);
+ v.visitTypeVariable(signature.substring(pos, end));
+ return end + 1;
+
+ default: // case 'L':
+ start = pos;
+ visited = false;
+ inner = false;
+ for (;;) {
+ switch (c = signature.charAt(pos++)) {
+ case '.':
+ case ';':
+ if (!visited) {
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ }
+ if (c == ';') {
+ v.visitEnd();
+ return pos;
+ }
+ start = pos;
+ visited = false;
+ inner = true;
+ break;
+
+ case '<':
+ name = signature.substring(start, pos - 1);
+ if (inner) {
+ v.visitInnerClassType(name);
+ } else {
+ v.visitClassType(name);
+ }
+ visited = true;
+ top: for (;;) {
+ switch (c = signature.charAt(pos)) {
+ case '>':
+ break top;
+ case '*':
+ ++pos;
+ v.visitTypeArgument();
+ break;
+ case '+':
+ case '-':
+ pos = parseType(signature,
+ pos + 1,
+ v.visitTypeArgument(c));
+ break;
+ default:
+ pos = parseType(signature,
+ pos,
+ v.visitTypeArgument('='));
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Makes the given visitor visit the signature of this
+ * {@link SignatureReader}. This signature is the one specified in the
+ * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+ * method is intended to be called on a {@link SignatureReader} that was
+ * created using a <i>ClassSignature</i> (such as the
+ * <code>signature</code> parameter of the
+ * {@link org.powermock.api.mockito.repackaged.asm.ClassVisitor#visit ClassVisitor.visit} method)
+ * or a <i>MethodTypeSignature</i> (such as the <code>signature</code>
+ * parameter of the
+ * {@link org.powermock.api.mockito.repackaged.asm.ClassVisitor#visitMethod ClassVisitor.visitMethod}
+ * method).
+ *
+ * @param v the visitor that must visit this signature.
+ */
+ public void accept(final SignatureVisitor v) {
+ String signature = this.signature;
+ int len = signature.length();
+ int pos;
+ char c;
+
+ if (signature.charAt(0) == '<') {
+ pos = 2;
+ do {
+ int end = signature.indexOf(':', pos);
+ v.visitFormalTypeParameter(signature.substring(pos - 1, end));
+ pos = end + 1;
+
+ c = signature.charAt(pos);
+ if (c == 'L' || c == '[' || c == 'T') {
+ pos = parseType(signature, pos, v.visitClassBound());
+ }
+
+ while ((c = signature.charAt(pos++)) == ':') {
+ pos = parseType(signature, pos, v.visitInterfaceBound());
+ }
+ } while (c != '>');
+ } else {
+ pos = 0;
+ }
+
+ if (signature.charAt(pos) == '(') {
+ pos++;
+ while (signature.charAt(pos) != ')') {
+ pos = parseType(signature, pos, v.visitParameterType());
+ }
+ pos = parseType(signature, pos + 1, v.visitReturnType());
+ while (pos < len) {
+ pos = parseType(signature, pos + 1, v.visitExceptionType());
+ }
+ } else {
+ pos = parseType(signature, pos, v.visitSuperclass());
+ while (pos < len) {
+ pos = parseType(signature, pos, v.visitInterface());
+ }
+ }
+ }
+
+ /**
+ * Makes the given visitor visit the signature of this
+ * {@link SignatureReader}. This signature is the one specified in the
+ * constructor (see {@link #SignatureReader(String) SignatureReader}). This
+ * method is intended to be called on a {@link SignatureReader} that was
+ * created using a <i>FieldTypeSignature</i>, such as the
+ * <code>signature</code> parameter of the
+ * {@link org.powermock.api.mockito.repackaged.asm.ClassVisitor#visitField
+ * ClassVisitor.visitField} or {@link
+ * org.powermock.api.mockito.repackaged.asm.MethodVisitor#visitLocalVariable
+ * MethodVisitor.visitLocalVariable} methods.
+ *
+ * @param v the visitor that must visit this signature.
+ */
+ public void acceptType(final SignatureVisitor v) {
+ parseType(this.signature, 0, v);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureVisitor.java
new file mode 100644
index 0000000..8e2c473
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureVisitor.java
@@ -0,0 +1,185 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.signature;
+
+/**
+ * A visitor to visit a generic signature. The methods of this interface must be
+ * called in one of the three following orders (the last one is the only valid
+ * order for a {@link SignatureVisitor} that is returned by a method of this
+ * interface): <ul> <li><i>ClassSignature</i> = (
+ * <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitSuperClass</tt>
+ * <tt>visitInterface</tt>* )</li>
+ * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>
+ * <tt>visitClassBound</tt>?
+ * <tt>visitInterfaceBound</tt>* )* ( <tt>visitParameterType</tt>*
+ * <tt>visitReturnType</tt>
+ * <tt>visitExceptionType</tt>* )</li> <li><i>TypeSignature</i> =
+ * <tt>visitBaseType</tt> | <tt>visitTypeVariable</tt> |
+ * <tt>visitArrayType</tt> | (
+ * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (
+ * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )*
+ * <tt>visitEnd</tt> ) )</li> </ul>
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public interface SignatureVisitor {
+
+ /**
+ * Wildcard for an "extends" type argument.
+ */
+ char EXTENDS = '+';
+
+ /**
+ * Wildcard for a "super" type argument.
+ */
+ char SUPER = '-';
+
+ /**
+ * Wildcard for a normal type argument.
+ */
+ char INSTANCEOF = '=';
+
+ /**
+ * Visits a formal type parameter.
+ *
+ * @param name the name of the formal parameter.
+ */
+ void visitFormalTypeParameter(String name);
+
+ /**
+ * Visits the class bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the class bound.
+ */
+ SignatureVisitor visitClassBound();
+
+ /**
+ * Visits an interface bound of the last visited formal type parameter.
+ *
+ * @return a non null visitor to visit the signature of the interface bound.
+ */
+ SignatureVisitor visitInterfaceBound();
+
+ /**
+ * Visits the type of the super class.
+ *
+ * @return a non null visitor to visit the signature of the super class
+ * type.
+ */
+ SignatureVisitor visitSuperclass();
+
+ /**
+ * Visits the type of an interface implemented by the class.
+ *
+ * @return a non null visitor to visit the signature of the interface type.
+ */
+ SignatureVisitor visitInterface();
+
+ /**
+ * Visits the type of a method parameter.
+ *
+ * @return a non null visitor to visit the signature of the parameter type.
+ */
+ SignatureVisitor visitParameterType();
+
+ /**
+ * Visits the return type of the method.
+ *
+ * @return a non null visitor to visit the signature of the return type.
+ */
+ SignatureVisitor visitReturnType();
+
+ /**
+ * Visits the type of a method exception.
+ *
+ * @return a non null visitor to visit the signature of the exception type.
+ */
+ SignatureVisitor visitExceptionType();
+
+ /**
+ * Visits a signature corresponding to a primitive type.
+ *
+ * @param descriptor the descriptor of the primitive type, or 'V' for
+ * <tt>void</tt>.
+ */
+ void visitBaseType(char descriptor);
+
+ /**
+ * Visits a signature corresponding to a type variable.
+ *
+ * @param name the name of the type variable.
+ */
+ void visitTypeVariable(String name);
+
+ /**
+ * Visits a signature corresponding to an array type.
+ *
+ * @return a non null visitor to visit the signature of the array element
+ * type.
+ */
+ SignatureVisitor visitArrayType();
+
+ /**
+ * Starts the visit of a signature corresponding to a class or interface
+ * type.
+ *
+ * @param name the internal name of the class or interface.
+ */
+ void visitClassType(String name);
+
+ /**
+ * Visits an inner class.
+ *
+ * @param name the local name of the inner class in its enclosing class.
+ */
+ void visitInnerClassType(String name);
+
+ /**
+ * Visits an unbounded type argument of the last visited class or inner
+ * class type.
+ */
+ void visitTypeArgument();
+
+ /**
+ * Visits a type argument of the last visited class or inner class type.
+ *
+ * @param wildcard '+', '-' or '='.
+ * @return a non null visitor to visit the signature of the type argument.
+ */
+ SignatureVisitor visitTypeArgument(char wildcard);
+
+ /**
+ * Ends the visit of a signature corresponding to a class or interface type.
+ */
+ void visitEnd();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureWriter.java
new file mode 100644
index 0000000..22e7d19
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/SignatureWriter.java
@@ -0,0 +1,207 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.signature;
+
+/**
+ * A signature visitor that generates signatures in string format.
+ *
+ * @author Thomas Hallgren
+ * @author Eric Bruneton
+ */
+public class SignatureWriter implements SignatureVisitor {
+
+ /**
+ * Buffer used to construct the signature.
+ */
+ private final StringBuffer buf = new StringBuffer();
+
+ /**
+ * Indicates if the signature contains formal type parameters.
+ */
+ private boolean hasFormals;
+
+ /**
+ * Indicates if the signature contains method parameter types.
+ */
+ private boolean hasParameters;
+
+ /**
+ * Stack used to keep track of class types that have arguments. Each element
+ * of this stack is a boolean encoded in one bit. The top of the stack is
+ * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+ * /2.
+ */
+ private int argumentStack;
+
+ /**
+ * Constructs a new {@link SignatureWriter} object.
+ */
+ public SignatureWriter() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the SignatureVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visitFormalTypeParameter(final String name) {
+ if (!hasFormals) {
+ hasFormals = true;
+ buf.append('<');
+ }
+ buf.append(name);
+ buf.append(':');
+ }
+
+ public SignatureVisitor visitClassBound() {
+ return this;
+ }
+
+ public SignatureVisitor visitInterfaceBound() {
+ buf.append(':');
+ return this;
+ }
+
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ return this;
+ }
+
+ public SignatureVisitor visitInterface() {
+ return this;
+ }
+
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (!hasParameters) {
+ hasParameters = true;
+ buf.append('(');
+ }
+ return this;
+ }
+
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (!hasParameters) {
+ buf.append('(');
+ }
+ buf.append(')');
+ return this;
+ }
+
+ public SignatureVisitor visitExceptionType() {
+ buf.append('^');
+ return this;
+ }
+
+ public void visitBaseType(final char descriptor) {
+ buf.append(descriptor);
+ }
+
+ public void visitTypeVariable(final String name) {
+ buf.append('T');
+ buf.append(name);
+ buf.append(';');
+ }
+
+ public SignatureVisitor visitArrayType() {
+ buf.append('[');
+ return this;
+ }
+
+ public void visitClassType(final String name) {
+ buf.append('L');
+ buf.append(name);
+ argumentStack *= 2;
+ }
+
+ public void visitInnerClassType(final String name) {
+ endArguments();
+ buf.append('.');
+ buf.append(name);
+ argumentStack *= 2;
+ }
+
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ buf.append('<');
+ }
+ buf.append('*');
+ }
+
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ buf.append('<');
+ }
+ if (wildcard != '=') {
+ buf.append(wildcard);
+ }
+ return this;
+ }
+
+ public void visitEnd() {
+ endArguments();
+ buf.append(';');
+ }
+
+ /**
+ * Returns the signature that was built by this signature writer.
+ *
+ * @return the signature that was built by this signature writer.
+ */
+ public String toString() {
+ return buf.toString();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Ends the formal type parameters section of the signature.
+ */
+ private void endFormals() {
+ if (hasFormals) {
+ hasFormals = false;
+ buf.append('>');
+ }
+ }
+
+ /**
+ * Ends the type arguments of a class or inner class type.
+ */
+ private void endArguments() {
+ if (argumentStack % 2 != 0) {
+ buf.append('>');
+ }
+ argumentStack /= 2;
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/package.html
new file mode 100644
index 0000000..5219cff
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/signature/package.html
@@ -0,0 +1,66 @@
+<!--
+ ~ ASM: a very small and fast Java bytecode manipulation framework
+ ~ Copyright (c) 2000-2007 INRIA, France Telecom
+ ~ All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions
+ ~ are met:
+ ~ 1. Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ 2. Redistributions in binary form must reproduce the above copyright
+ ~ notice, this list of conditions and the following disclaimer in the
+ ~ documentation and/or other materials provided with the distribution.
+ ~ 3. Neither the name of the copyright holders nor the names of its
+ ~ contributors may be used to endorse or promote products derived from
+ ~ this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ~ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ~ THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides support for type signatures.
+
+ at since ASM 2.0
+</body>
+</html>
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AbstractInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AbstractInsnNode.java
new file mode 100644
index 0000000..ea47f5f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AbstractInsnNode.java
@@ -0,0 +1,233 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A node that represents a bytecode instruction. <i>An instruction can appear
+ * at most once in at most one {@link InsnList} at a time</i>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class AbstractInsnNode {
+
+ /**
+ * The type of {@link InsnNode} instructions.
+ */
+ public static final int INSN = 0;
+
+ /**
+ * The type of {@link IntInsnNode} instructions.
+ */
+ public static final int INT_INSN = 1;
+
+ /**
+ * The type of {@link VarInsnNode} instructions.
+ */
+ public static final int VAR_INSN = 2;
+
+ /**
+ * The type of {@link TypeInsnNode} instructions.
+ */
+ public static final int TYPE_INSN = 3;
+
+ /**
+ * The type of {@link FieldInsnNode} instructions.
+ */
+ public static final int FIELD_INSN = 4;
+
+ /**
+ * The type of {@link MethodInsnNode} instructions.
+ */
+ public static final int METHOD_INSN = 5;
+
+ /**
+ * The type of {@link JumpInsnNode} instructions.
+ */
+ public static final int JUMP_INSN = 6;
+
+ /**
+ * The type of {@link LabelNode} "instructions".
+ */
+ public static final int LABEL = 7;
+
+ /**
+ * The type of {@link LdcInsnNode} instructions.
+ */
+ public static final int LDC_INSN = 8;
+
+ /**
+ * The type of {@link IincInsnNode} instructions.
+ */
+ public static final int IINC_INSN = 9;
+
+ /**
+ * The type of {@link TableSwitchInsnNode} instructions.
+ */
+ public static final int TABLESWITCH_INSN = 10;
+
+ /**
+ * The type of {@link LookupSwitchInsnNode} instructions.
+ */
+ public static final int LOOKUPSWITCH_INSN = 11;
+
+ /**
+ * The type of {@link MultiANewArrayInsnNode} instructions.
+ */
+ public static final int MULTIANEWARRAY_INSN = 12;
+
+ /**
+ * The type of {@link FrameNode} "instructions".
+ */
+ public static final int FRAME = 13;
+
+ /**
+ * The type of {@link LineNumberNode} "instructions".
+ */
+ public static final int LINE = 14;
+
+ /**
+ * The opcode of this instruction.
+ */
+ protected int opcode;
+
+ /**
+ * Previous instruction in the list to which this instruction belongs.
+ */
+ AbstractInsnNode prev;
+
+ /**
+ * Next instruction in the list to which this instruction belongs.
+ */
+ AbstractInsnNode next;
+
+ /**
+ * Index of this instruction in the list to which it belongs. The value of
+ * this field is correct only when {@link InsnList#cache} is not null. A
+ * value of -1 indicates that this instruction does not belong to any
+ * {@link InsnList}.
+ */
+ int index;
+
+ /**
+ * Constructs a new {@link AbstractInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed.
+ */
+ protected AbstractInsnNode(final int opcode) {
+ this.opcode = opcode;
+ this.index = -1;
+ }
+
+ /**
+ * Returns the clone of the given label.
+ *
+ * @param label a label.
+ * @param map a map from LabelNodes to cloned LabelNodes.
+ * @return the clone of the given label.
+ */
+ static LabelNode clone(final LabelNode label, final Map map) {
+ return (LabelNode) map.get(label);
+ }
+
+ /**
+ * Returns the clones of the given labels.
+ *
+ * @param labels a list of labels.
+ * @param map a map from LabelNodes to cloned LabelNodes.
+ * @return the clones of the given labels.
+ */
+ static LabelNode[] clone(final List labels, final Map map) {
+ LabelNode[] clones = new LabelNode[labels.size()];
+ for (int i = 0; i < clones.length; ++i) {
+ clones[i] = (LabelNode) map.get(labels.get(i));
+ }
+ return clones;
+ }
+
+ /**
+ * Returns the opcode of this instruction.
+ *
+ * @return the opcode of this instruction.
+ */
+ public int getOpcode() {
+ return opcode;
+ }
+
+ /**
+ * Returns the type of this instruction.
+ *
+ * @return the type of this instruction, i.e. one the constants defined in
+ * this class.
+ */
+ public abstract int getType();
+
+ /**
+ * Returns the previous instruction in the list to which this instruction
+ * belongs, if any.
+ *
+ * @return the previous instruction in the list to which this instruction
+ * belongs, if any. May be <tt>null</tt>.
+ */
+ public AbstractInsnNode getPrevious() {
+ return prev;
+ }
+
+ /**
+ * Returns the next instruction in the list to which this instruction
+ * belongs, if any.
+ *
+ * @return the next instruction in the list to which this instruction
+ * belongs, if any. May be <tt>null</tt>.
+ */
+ public AbstractInsnNode getNext() {
+ return next;
+ }
+
+ /**
+ * Makes the given code visitor visit this instruction.
+ *
+ * @param cv a code visitor.
+ */
+ public abstract void accept(final MethodVisitor cv);
+
+ /**
+ * Returns a copy of this instruction.
+ *
+ * @param labels a map from LabelNodes to cloned LabelNodes.
+ * @return a copy of this instruction. The returned instruction does not
+ * belong to any {@link InsnList}.
+ */
+ public abstract AbstractInsnNode clone(final Map labels);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AnnotationNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AnnotationNode.java
new file mode 100644
index 0000000..4bcdf7a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/AnnotationNode.java
@@ -0,0 +1,191 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A node that represents an annotationn.
+ *
+ * @author Eric Bruneton
+ */
+public class AnnotationNode implements AnnotationVisitor {
+
+ /**
+ * The class descriptor of the annotation class.
+ */
+ public String desc;
+
+ /**
+ * The name value pairs of this annotation. Each name value pair is stored
+ * as two consecutive elements in the list. The name is a {@link String},
+ * and the value may be a {@link Byte}, {@link Boolean}, {@link Character},
+ * {@link Short}, {@link Integer}, {@link Long}, {@link Float},
+ * {@link Double}, {@link String} or {@link org.powermock.api.mockito.repackaged.asm.Type}, or an
+ * two elements String array (for enumeration values), a
+ * {@link AnnotationNode}, or a {@link List} of values of one of the
+ * preceding types. The list may be <tt>null</tt> if there is no name
+ * value pair.
+ */
+ public List values;
+
+ /**
+ * Constructs a new {@link AnnotationNode}.
+ *
+ * @param desc the class descriptor of the annotation class.
+ */
+ public AnnotationNode(final String desc) {
+ this.desc = desc;
+ }
+
+ /**
+ * Constructs a new {@link AnnotationNode} to visit an array value.
+ *
+ * @param values where the visited values must be stored.
+ */
+ AnnotationNode(final List values) {
+ this.values = values;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor interface
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit a given annotation value.
+ *
+ * @param av an annotation visitor. Maybe <tt>null</tt>.
+ * @param name the value name.
+ * @param value the actual value.
+ */
+ static void accept(
+ final AnnotationVisitor av,
+ final String name,
+ final Object value)
+ {
+ if (av != null) {
+ if (value instanceof String[]) {
+ String[] typeconst = (String[]) value;
+ av.visitEnum(name, typeconst[0], typeconst[1]);
+ } else if (value instanceof AnnotationNode) {
+ AnnotationNode an = (AnnotationNode) value;
+ an.accept(av.visitAnnotation(name, an.desc));
+ } else if (value instanceof List) {
+ AnnotationVisitor v = av.visitArray(name);
+ List array = (List) value;
+ for (int j = 0; j < array.size(); ++j) {
+ accept(v, null, array.get(j));
+ }
+ v.visitEnd();
+ } else {
+ av.visit(name, value);
+ }
+ }
+ }
+
+ public void visit(final String name, final Object value) {
+ if (values == null) {
+ values = new ArrayList(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ values.add(value);
+ }
+
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ if (values == null) {
+ values = new ArrayList(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ values.add(new String[] { desc, value });
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ if (values == null) {
+ values = new ArrayList(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ AnnotationNode annotation = new AnnotationNode(desc);
+ values.add(annotation);
+ return annotation;
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ if (values == null) {
+ values = new ArrayList(this.desc != null ? 2 : 1);
+ }
+ if (this.desc != null) {
+ values.add(name);
+ }
+ List array = new ArrayList();
+ values.add(array);
+ return new AnnotationNode(array);
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept methods
+ // ------------------------------------------------------------------------
+
+ public void visitEnd() {
+ }
+
+ /**
+ * Makes the given visitor visit this annotation.
+ *
+ * @param av an annotation visitor. Maybe <tt>null</tt>.
+ */
+ public void accept(final AnnotationVisitor av) {
+ if (av != null) {
+ if (values != null) {
+ for (int i = 0; i < values.size(); i += 2) {
+ String name = (String) values.get(i);
+ Object value = values.get(i + 1);
+ accept(av, name, value);
+ }
+ }
+ av.visitEnd();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/ClassNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/ClassNode.java
new file mode 100644
index 0000000..69b7315
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/ClassNode.java
@@ -0,0 +1,280 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A node that represents a class.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassNode extends MemberNode implements ClassVisitor {
+
+ /**
+ * The class version.
+ */
+ public int version;
+
+ /**
+ * The class's access flags (see {@link org.powermock.api.mockito.repackaged.asm.Opcodes}). This
+ * field also indicates if the class is deprecated.
+ */
+ public int access;
+
+ /**
+ * The internal name of the class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ */
+ public String name;
+
+ /**
+ * The signature of the class. Mayt be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The internal of name of the super class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}). For
+ * interfaces, the super class is {@link Object}. May be <tt>null</tt>,
+ * but only for the {@link Object} class.
+ */
+ public String superName;
+
+ /**
+ * The internal names of the class's interfaces (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}). This
+ * list is a list of {@link String} objects.
+ */
+ public List interfaces;
+
+ /**
+ * The name of the source file from which this class was compiled. May be
+ * <tt>null</tt>.
+ */
+ public String sourceFile;
+
+ /**
+ * Debug information to compute the correspondance between source and
+ * compiled elements of the class. May be <tt>null</tt>.
+ */
+ public String sourceDebug;
+
+ /**
+ * The internal name of the enclosing class of the class. May be
+ * <tt>null</tt>.
+ */
+ public String outerClass;
+
+ /**
+ * The name of the method that contains the class, or <tt>null</tt> if the
+ * class is not enclosed in a method.
+ */
+ public String outerMethod;
+
+ /**
+ * The descriptor of the method that contains the class, or <tt>null</tt>
+ * if the class is not enclosed in a method.
+ */
+ public String outerMethodDesc;
+
+ /**
+ * Informations about the inner classes of this class. This list is a list
+ * of {@link InnerClassNode} objects.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.InnerClassNode
+ */
+ public List innerClasses;
+
+ /**
+ * The fields of this class. This list is a list of {@link FieldNode}
+ * objects.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.FieldNode
+ */
+ public List fields;
+
+ /**
+ * The methods of this class. This list is a list of {@link MethodNode}
+ * objects.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.MethodNode
+ */
+ public List methods;
+
+ /**
+ * Constructs a new {@link ClassNode}.
+ */
+ public ClassNode() {
+ this.interfaces = new ArrayList();
+ this.innerClasses = new ArrayList();
+ this.fields = new ArrayList();
+ this.methods = new ArrayList();
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ this.version = version;
+ this.access = access;
+ this.name = name;
+ this.signature = signature;
+ this.superName = superName;
+ if (interfaces != null) {
+ this.interfaces.addAll(Arrays.asList(interfaces));
+ }
+ }
+
+ public void visitSource(final String file, final String debug) {
+ sourceFile = file;
+ sourceDebug = debug;
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ outerClass = owner;
+ outerMethod = name;
+ outerMethodDesc = desc;
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ InnerClassNode icn = new InnerClassNode(name,
+ outerName,
+ innerName,
+ access);
+ innerClasses.add(icn);
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ FieldNode fn = new FieldNode(access, name, desc, signature, value);
+ fields.add(fn);
+ return fn;
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ MethodNode mn = new MethodNode(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ methods.add(mn);
+ return mn;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept method
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given class visitor visit this class.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ // visits header
+ String[] interfaces = new String[this.interfaces.size()];
+ this.interfaces.toArray(interfaces);
+ cv.visit(version, access, name, signature, superName, interfaces);
+ // visits source
+ if (sourceFile != null || sourceDebug != null) {
+ cv.visitSource(sourceFile, sourceDebug);
+ }
+ // visits outer class
+ if (outerClass != null) {
+ cv.visitOuterClass(outerClass, outerMethod, outerMethodDesc);
+ }
+ // visits attributes
+ int i, n;
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
+ an.accept(cv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
+ an.accept(cv.visitAnnotation(an.desc, false));
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ cv.visitAttribute((Attribute) attrs.get(i));
+ }
+ // visits inner classes
+ for (i = 0; i < innerClasses.size(); ++i) {
+ ((InnerClassNode) innerClasses.get(i)).accept(cv);
+ }
+ // visits fields
+ for (i = 0; i < fields.size(); ++i) {
+ ((FieldNode) fields.get(i)).accept(cv);
+ }
+ // visits methods
+ for (i = 0; i < methods.size(); ++i) {
+ ((MethodNode) methods.get(i)).accept(cv);
+ }
+ // visits end
+ cv.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldInsnNode.java
new file mode 100644
index 0000000..fe6c09b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldInsnNode.java
@@ -0,0 +1,103 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a field instruction. A field instruction is an
+ * instruction that loads or stores the value of a field of an object.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldInsnNode extends AbstractInsnNode {
+
+ /**
+ * The internal name of the field's owner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ */
+ public String owner;
+
+ /**
+ * The field's name.
+ */
+ public String name;
+
+ /**
+ * The field's descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link FieldInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner the internal name of the field's owner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ * @param name the field's name.
+ * @param desc the field's descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public FieldInsnNode(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be GETSTATIC,
+ * PUTSTATIC, GETFIELD or PUTFIELD.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return FIELD_INSN;
+ }
+
+ public void accept(final MethodVisitor cv) {
+ cv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new FieldInsnNode(opcode, owner, name, desc);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldNode.java
new file mode 100644
index 0000000..02c5da5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FieldNode.java
@@ -0,0 +1,127 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+
+/**
+ * A node that represents a field.
+ *
+ * @author Eric Bruneton
+ */
+public class FieldNode extends MemberNode implements FieldVisitor {
+
+ /**
+ * The field's access flags (see {@link org.powermock.api.mockito.repackaged.asm.Opcodes}). This
+ * field also indicates if the field is synthetic and/or deprecated.
+ */
+ public int access;
+
+ /**
+ * The field's name.
+ */
+ public String name;
+
+ /**
+ * The field's descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * The field's signature. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The field's initial value. This field, which may be <tt>null</tt> if
+ * the field does not have an initial value, must be an {@link Integer}, a
+ * {@link Float}, a {@link Long}, a {@link Double} or a {@link String}.
+ */
+ public Object value;
+
+ /**
+ * Constructs a new {@link FieldNode}.
+ *
+ * @param access the field's access flags (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Opcodes}). This parameter also indicates
+ * if the field is synthetic and/or deprecated.
+ * @param name the field's name.
+ * @param desc the field's descriptor (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type Type}).
+ * @param signature the field's signature.
+ * @param value the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value, must
+ * be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ */
+ public FieldNode(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.value = value;
+ }
+
+ /**
+ * Makes the given class visitor visit this field.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
+ if (fv == null) {
+ return;
+ }
+ int i, n;
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
+ an.accept(fv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
+ an.accept(fv.visitAnnotation(an.desc, false));
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ fv.visitAttribute((Attribute) attrs.get(i));
+ }
+ fv.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FrameNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FrameNode.java
new file mode 100644
index 0000000..f39b095
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/FrameNode.java
@@ -0,0 +1,208 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A node that represents a stack map frame. These nodes are pseudo instruction
+ * nodes in order to be inserted in an instruction list. In fact these nodes
+ * must(*) be inserted <i>just before</i> any instruction node <b>i</b> that
+ * follows an unconditionnal branch instruction such as GOTO or THROW, that is
+ * the target of a jump instruction, or that starts an exception handler block.
+ * The stack map frame types must describe the values of the local variables and
+ * of the operand stack elements <i>just before</i> <b>i</b> is executed. <br>
+ * <br> (*) this is mandatory only for classes whose version is greater than or
+ * equal to {@link Opcodes#V1_6 V1_6}.
+ *
+ * @author Eric Bruneton
+ */
+public class FrameNode extends AbstractInsnNode {
+
+ /**
+ * The type of this frame. Must be {@link Opcodes#F_NEW} for expanded
+ * frames, or {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for compressed frames.
+ */
+ public int type;
+
+ /**
+ * The types of the local variables of this stack map frame. Elements of
+ * this list can be Integer, String or LabelNode objects (for primitive,
+ * reference and uninitialized types respectively - see
+ * {@link MethodVisitor}).
+ */
+ public List local;
+
+ /**
+ * The types of the operand stack elements of this stack map frame. Elements
+ * of this list can be Integer, String or LabelNode objects (for primitive,
+ * reference and uninitialized types respectively - see
+ * {@link MethodVisitor}).
+ */
+ public List stack;
+
+ private FrameNode() {
+ super(-1);
+ }
+
+ /**
+ * Constructs a new {@link FrameNode}.
+ *
+ * @param type the type of this frame. Must be {@link Opcodes#F_NEW} for
+ * expanded frames, or {@link Opcodes#F_FULL},
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_CHOP},
+ * {@link Opcodes#F_SAME} or {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_SAME1} for compressed frames.
+ * @param nLocal number of local variables of this stack map frame.
+ * @param local the types of the local variables of this stack map frame.
+ * Elements of this list can be Integer, String or LabelNode objects
+ * (for primitive, reference and uninitialized types respectively -
+ * see {@link MethodVisitor}).
+ * @param nStack number of operand stack elements of this stack map frame.
+ * @param stack the types of the operand stack elements of this stack map
+ * frame. Elements of this list can be Integer, String or LabelNode
+ * objects (for primitive, reference and uninitialized types
+ * respectively - see {@link MethodVisitor}).
+ */
+ public FrameNode(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ super(-1);
+ this.type = type;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ this.local = asList(nLocal, local);
+ this.stack = asList(nStack, stack);
+ break;
+ case Opcodes.F_APPEND:
+ this.local = asList(nLocal, local);
+ break;
+ case Opcodes.F_CHOP:
+ this.local = asList(nLocal, local);
+ break;
+ case Opcodes.F_SAME:
+ break;
+ case Opcodes.F_SAME1:
+ this.stack = asList(1, stack);
+ break;
+ }
+ }
+
+ private static List asList(final int n, final Object[] o) {
+ return Arrays.asList(o).subList(0, n);
+ }
+
+ private static Object[] asArray(final List l) {
+ Object[] objs = new Object[l.size()];
+ for (int i = 0; i < objs.length; ++i) {
+ Object o = l.get(i);
+ if (o instanceof LabelNode) {
+ o = ((LabelNode) o).getLabel();
+ }
+ objs[i] = o;
+ }
+ return objs;
+ }
+
+ public int getType() {
+ return FRAME;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit this stack map frame.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mv.visitFrame(type,
+ local.size(),
+ asArray(local),
+ stack.size(),
+ asArray(stack));
+ break;
+ case Opcodes.F_APPEND:
+ mv.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_CHOP:
+ mv.visitFrame(type, local.size(), asArray(local), 0, null);
+ break;
+ case Opcodes.F_SAME:
+ mv.visitFrame(type, 0, null, 0, null);
+ break;
+ case Opcodes.F_SAME1:
+ mv.visitFrame(type, 0, null, 1, asArray(stack));
+ break;
+ }
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ FrameNode clone = new FrameNode();
+ clone.type = type;
+ if (local != null) {
+ clone.local = new ArrayList();
+ for (int i = 0; i < local.size(); ++i) {
+ Object l = local.get(i);
+ if (l instanceof LabelNode) {
+ l = labels.get(l);
+ }
+ clone.local.add(l);
+ }
+ }
+ if (stack != null) {
+ clone.stack = new ArrayList();
+ for (int i = 0; i < stack.size(); ++i) {
+ Object s = stack.get(i);
+ if (s instanceof LabelNode) {
+ s = labels.get(s);
+ }
+ clone.stack.add(s);
+ }
+ }
+ return clone;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IincInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IincInsnNode.java
new file mode 100644
index 0000000..2f90593
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IincInsnNode.java
@@ -0,0 +1,77 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.Map;
+
+/**
+ * A node that represents an IINC instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class IincInsnNode extends AbstractInsnNode {
+
+ /**
+ * Index of the local variable to be incremented.
+ */
+ public int var;
+
+ /**
+ * Amount to increment the local variable by.
+ */
+ public int incr;
+
+ /**
+ * Constructs a new {@link IincInsnNode}.
+ *
+ * @param var index of the local variable to be incremented.
+ * @param incr increment amount to increment the local variable by.
+ */
+ public IincInsnNode(final int var, final int incr) {
+ super(Opcodes.IINC);
+ this.var = var;
+ this.incr = incr;
+ }
+
+ public int getType() {
+ return IINC_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitIincInsn(var, incr);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new IincInsnNode(var, incr);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InnerClassNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InnerClassNode.java
new file mode 100644
index 0000000..871114c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InnerClassNode.java
@@ -0,0 +1,101 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+
+/**
+ * A node that represents an inner class.
+ *
+ * @author Eric Bruneton
+ */
+public class InnerClassNode {
+
+ /**
+ * The internal name of an inner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ */
+ public String name;
+
+ /**
+ * The internal name of the class to which the inner class belongs (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}). May
+ * be <tt>null</tt>.
+ */
+ public String outerName;
+
+ /**
+ * The (simple) name of the inner class inside its enclosing class. May be
+ * <tt>null</tt> for anonymous inner classes.
+ */
+ public String innerName;
+
+ /**
+ * The access flags of the inner class as originally declared in the
+ * enclosing class.
+ */
+ public int access;
+
+ /**
+ * Constructs a new {@link InnerClassNode}.
+ *
+ * @param name the internal name of an inner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ * @param outerName the internal name of the class to which the inner class
+ * belongs (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ * May be <tt>null</tt>.
+ * @param innerName the (simple) name of the inner class inside its
+ * enclosing class. May be <tt>null</tt> for anonymous inner
+ * classes.
+ * @param access the access flags of the inner class as originally declared
+ * in the enclosing class.
+ */
+ public InnerClassNode(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ this.name = name;
+ this.outerName = outerName;
+ this.innerName = innerName;
+ this.access = access;
+ }
+
+ /**
+ * Makes the given class visitor visit this inner class.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnList.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnList.java
new file mode 100644
index 0000000..03d0c95
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnList.java
@@ -0,0 +1,640 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+/**
+ * A doubly linked list of {@link AbstractInsnNode} objects. <i>This
+ * implementation is not thread safe</i>.
+ */
+public class InsnList {
+
+ /**
+ * Indicates if preconditions of methods of this class must be checked.
+ * <i>Checking preconditions causes the {@link #indexOf indexOf},
+ * {@link #set set}, {@link #insert(AbstractInsnNode, AbstractInsnNode)},
+ * {@link #insert(AbstractInsnNode, InsnList)}, {@link #remove remove} and
+ * {@link #clear} methods to execute in O(n) time instead of O(1)</i>.
+ */
+ public static boolean check;
+
+ /**
+ * The number of instructions in this list.
+ */
+ private int size;
+
+ /**
+ * The first instruction in this list. May be <tt>null</tt>.
+ */
+ private AbstractInsnNode first;
+
+ /**
+ * The last instruction in this list. May be <tt>null</tt>.
+ */
+ private AbstractInsnNode last;
+
+ /**
+ * A cache of the instructions of this list. This cache is used to improve
+ * the performance of the {@link #get} method.
+ */
+ private AbstractInsnNode[] cache;
+
+ /**
+ * Returns the number of instructions in this list.
+ *
+ * @return the number of instructions in this list.
+ */
+ public int size() {
+ return size;
+ }
+
+ /**
+ * Returns the first instruction in this list.
+ *
+ * @return the first instruction in this list, or <tt>null</tt> if the
+ * list is empty.
+ */
+ public AbstractInsnNode getFirst() {
+ return first;
+ }
+
+ /**
+ * Returns the last instruction in this list.
+ *
+ * @return the last instruction in this list, or <tt>null</tt> if the list
+ * is empty.
+ */
+ public AbstractInsnNode getLast() {
+ return last;
+ }
+
+ /**
+ * Returns the instruction whose index is given. This method builds a cache
+ * of the instructions in this list to avoid scanning the whole list each
+ * time it is called. Once the cache is built, this method run in constant
+ * time. This cache is invalidated by all the methods that modify the list.
+ *
+ * @param index the index of the instruction that must be returned.
+ * @return the instruction whose index is given.
+ * @throws IndexOutOfBoundsException if (index < 0 || index >= size()).
+ */
+ public AbstractInsnNode get(final int index) {
+ if (index < 0 || index >= size) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return cache[index];
+ }
+
+ /**
+ * Returns <tt>true</tt> if the given instruction belongs to this list.
+ * This method always scans the instructions of this list until it finds the
+ * given instruction or reaches the end of the list.
+ *
+ * @param insn an instruction.
+ * @return <tt>true</tt> if the given instruction belongs to this list.
+ */
+ public boolean contains(final AbstractInsnNode insn) {
+ AbstractInsnNode i = first;
+ while (i != null && i != insn) {
+ i = i.next;
+ }
+ return i != null;
+ }
+
+ /**
+ * Returns the index of the given instruction in this list. This method
+ * builds a cache of the instruction indexes to avoid scanning the whole
+ * list each time it is called. Once the cache is built, this method run in
+ * constant time. The cache is invalidated by all the methods that modify
+ * the list.
+ *
+ * @param insn an instruction <i>of this list</i>.
+ * @return the index of the given instruction in this list. <i>The result of
+ * this method is undefined if the given instruction does not belong
+ * to this list</i>. Use {@link #contains contains} to test if an
+ * instruction belongs to an instruction list or not.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt> and
+ * if insn does not belong to this list.
+ */
+ public int indexOf(final AbstractInsnNode insn) {
+ if (check && !contains(insn)) {
+ throw new IllegalArgumentException();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return insn.index;
+ }
+
+ /**
+ * Makes the given visitor visit all of the instructions in this list.
+ *
+ * @param mv the method visitor that must visit the instructions.
+ */
+ public void accept(final MethodVisitor mv) {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ insn.accept(mv);
+ insn = insn.next;
+ }
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @return an iterator over the instructions in this list.
+ */
+ public ListIterator iterator() {
+ return iterator(0);
+ }
+
+ /**
+ * Returns an iterator over the instructions in this list.
+ *
+ * @return an iterator over the instructions in this list.
+ */
+ public ListIterator iterator(int index) {
+ return new InsnListIterator(index);
+ }
+
+ /**
+ * Returns an array containing all of the instructions in this list.
+ *
+ * @return an array containing all of the instructions in this list.
+ */
+ public AbstractInsnNode[] toArray() {
+ int i = 0;
+ AbstractInsnNode elem = first;
+ AbstractInsnNode[] insns = new AbstractInsnNode[size];
+ while (elem != null) {
+ insns[i] = elem;
+ elem.index = i++;
+ elem = elem.next;
+ }
+ return insns;
+ }
+
+ /**
+ * Replaces an instruction of this list with another instruction.
+ *
+ * @param location an instruction <i>of this list</i>.
+ * @param insn another instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if i does not belong to this list or if insn belongs to an
+ * instruction list.
+ */
+ public void set(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ if (check && !(contains(location) && insn.index == -1)) {
+ throw new IllegalArgumentException();
+ }
+ AbstractInsnNode next = location.next;
+ insn.next = next;
+ if (next != null) {
+ next.prev = insn;
+ } else {
+ last = insn;
+ }
+ AbstractInsnNode prev = location.prev;
+ insn.prev = prev;
+ if (prev != null) {
+ prev.next = insn;
+ } else {
+ first = insn;
+ }
+ if (cache != null) {
+ int index = location.index;
+ cache[index] = insn;
+ insn.index = index;
+ } else {
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+ location.index = -1; // i no longer belongs to an InsnList
+ location.prev = null;
+ location.next = null;
+ }
+
+ /**
+ * Adds the given instruction to the end of this list.
+ *
+ * @param insn an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if insn belongs to an instruction list.
+ */
+ public void add(final AbstractInsnNode insn) {
+ if (check && insn.index != -1) {
+ throw new IllegalArgumentException();
+ }
+ ++size;
+ if (last == null) {
+ first = insn;
+ last = insn;
+ } else {
+ last.next = insn;
+ insn.prev = last;
+ }
+ last = insn;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Adds the given instructions to the end of this list.
+ *
+ * @param insns an instruction list, which is cleared during the process.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if insn == this.
+ */
+ public void add(final InsnList insns) {
+ if (check && insns == this) {
+ throw new IllegalArgumentException();
+ }
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ if (last == null) {
+ first = insns.first;
+ last = insns.last;
+ } else {
+ AbstractInsnNode elem = insns.first;
+ last.next = elem;
+ elem.prev = last;
+ last = insns.last;
+ }
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction at the begining of this list.
+ *
+ * @param insn an instruction, <i>which must not belong to any
+ * {@link InsnList}</i>.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if insn belongs to an instruction list.
+ */
+ public void insert(final AbstractInsnNode insn) {
+ if (check && insn.index != -1) {
+ throw new IllegalArgumentException();
+ }
+ ++size;
+ if (first == null) {
+ first = insn;
+ last = insn;
+ } else {
+ first.prev = insn;
+ insn.next = first;
+ }
+ first = insn;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions at the begining of this list.
+ *
+ * @param insns an instruction list, which is cleared during the process.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if insn == this.
+ */
+ public void insert(final InsnList insns) {
+ if (check && insns == this) {
+ throw new IllegalArgumentException();
+ }
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ if (first == null) {
+ first = insns.first;
+ last = insns.last;
+ } else {
+ AbstractInsnNode elem = insns.last;
+ first.prev = elem;
+ elem.next = first;
+ first = insns.first;
+ }
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction after the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> after which insn must be
+ * inserted.
+ * @param insn the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if i does not belong to this list or if insn belongs to an
+ * instruction list.
+ */
+ public void insert(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ if (check && !(contains(location) && insn.index == -1)) {
+ throw new IllegalArgumentException();
+ }
+ ++size;
+ AbstractInsnNode next = location.next;
+ if (next == null) {
+ last = insn;
+ } else {
+ next.prev = insn;
+ }
+ location.next = insn;
+ insn.next = next;
+ insn.prev = location;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions after the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> after which the instructions
+ * must be inserted.
+ * @param insns the instruction list to be inserted, which is cleared during
+ * the process.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if i does not belong to this list or if insns == this.
+ */
+ public void insert(final AbstractInsnNode location, final InsnList insns) {
+ if (check && !(contains(location) && insns != this)) {
+ throw new IllegalArgumentException();
+ }
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ AbstractInsnNode ifirst = insns.first;
+ AbstractInsnNode ilast = insns.last;
+ AbstractInsnNode next = location.next;
+ if (next == null) {
+ last = ilast;
+ } else {
+ next.prev = ilast;
+ }
+ location.next = ifirst;
+ ilast.next = next;
+ ifirst.prev = location;
+ cache = null;
+ insns.removeAll(false);
+ }
+
+ /**
+ * Inserts the given instruction before the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> before which insn must be
+ * inserted.
+ * @param insn the instruction to be inserted, <i>which must not belong to
+ * any {@link InsnList}</i>.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if i does not belong to this list or if insn belongs to an
+ * instruction list.
+ */
+ public void insertBefore(final AbstractInsnNode location, final AbstractInsnNode insn) {
+ if (check && !(contains(location) && insn.index == -1)) {
+ throw new IllegalArgumentException();
+ }
+ ++size;
+ AbstractInsnNode prev = location.prev;
+ if (prev == null) {
+ first = insn;
+ } else {
+ prev.next = insn;
+ }
+ location.prev = insn;
+ insn.next = location;
+ insn.prev = prev;
+ cache = null;
+ insn.index = 0; // insn now belongs to an InsnList
+ }
+
+ /**
+ * Inserts the given instructions before the specified instruction.
+ *
+ * @param location an instruction <i>of this list</i> before which the instructions
+ * must be inserted.
+ * @param insns the instruction list to be inserted, which is cleared during
+ * the process.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if i does not belong to this list or if insns == this.
+ */
+ public void insertBefore(final AbstractInsnNode location, final InsnList insns) {
+ if (check && !(contains(location ) && insns != this)) {
+ throw new IllegalArgumentException();
+ }
+ if (insns.size == 0) {
+ return;
+ }
+ size += insns.size;
+ AbstractInsnNode ifirst = insns.first;
+ AbstractInsnNode ilast = insns.last;
+ AbstractInsnNode prev = location .prev;
+ if (prev == null) {
+ first = ifirst;
+ } else {
+ prev.next = ifirst;
+ }
+ location .prev = ilast;
+ ilast.next = location ;
+ ifirst.prev = prev;
+ cache = null;
+ insns.removeAll(false);
+ }
+
+
+
+ /**
+ * Removes the given instruction from this list.
+ *
+ * @param insn the instruction <i>of this list</i> that must be removed.
+ * @throws IllegalArgumentException if {@link #check} is <tt>true</tt>,
+ * and if insn does not belong to this list.
+ */
+ public void remove(final AbstractInsnNode insn) {
+ if (check && !contains(insn)) {
+ throw new IllegalArgumentException();
+ }
+ --size;
+ AbstractInsnNode next = insn.next;
+ AbstractInsnNode prev = insn.prev;
+ if (next == null) {
+ if (prev == null) {
+ first = null;
+ last = null;
+ } else {
+ prev.next = null;
+ last = prev;
+ }
+ } else {
+ if (prev == null) {
+ first = next;
+ next.prev = null;
+ } else {
+ prev.next = next;
+ next.prev = prev;
+ }
+ }
+ cache = null;
+ insn.index = -1; // insn no longer belongs to an InsnList
+ insn.prev = null;
+ insn.next = null;
+ }
+
+ /**
+ * Removes all of the instructions of this list.
+ *
+ * @param mark if the instructions must be marked as no longer belonging to
+ * any {@link InsnList}.
+ */
+ private void removeAll(final boolean mark) {
+ if (mark) {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ AbstractInsnNode next = insn.next;
+ insn.index = -1; // insn no longer belongs to an InsnList
+ insn.prev = null;
+ insn.next = null;
+ insn = next;
+ }
+ }
+ size = 0;
+ first = null;
+ last = null;
+ cache = null;
+ }
+
+ /**
+ * Removes all of the instructions of this list.
+ */
+ public void clear() {
+ removeAll(check);
+ }
+
+ /**
+ * Reset all labels in the instruction list. This method should be called
+ * before reusing same instructions list between several
+ * <code>ClassWriter</code>s.
+ */
+ public void resetLabels() {
+ AbstractInsnNode insn = first;
+ while (insn != null) {
+ if (insn instanceof LabelNode) {
+ ((LabelNode) insn).resetLabel();
+ }
+ insn = insn.next;
+ }
+ }
+
+ private final class InsnListIterator implements ListIterator {
+ AbstractInsnNode next;
+ AbstractInsnNode prev;
+
+ private InsnListIterator(int index) {
+ if(index==size()) {
+ next = null;
+ prev = getLast();
+ } else {
+ next = get(index);
+ prev = next.prev;
+ }
+ }
+
+ public boolean hasNext() {
+ return next != null;
+ }
+
+ public Object next() {
+ if (next == null) {
+ throw new NoSuchElementException();
+ }
+ AbstractInsnNode result = next;
+ prev = result;
+ next = result.next;
+ return result;
+ }
+
+ public void remove() {
+ InsnList.this.remove(prev);
+ prev = prev.prev;
+ }
+
+ public boolean hasPrevious() {
+ return prev != null;
+ }
+
+ public Object previous() {
+ AbstractInsnNode result = prev;
+ next = result;
+ prev = result.prev;
+ return result;
+ }
+
+ public int nextIndex() {
+ if (next == null) {
+ return size();
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return next.index;
+ }
+
+ public int previousIndex() {
+ if (prev == null) {
+ return -1;
+ }
+ if (cache == null) {
+ cache = toArray();
+ }
+ return prev.index;
+ }
+
+ public void add(Object o) {
+ InsnList.this.insertBefore(next, (AbstractInsnNode) o);
+ prev = (AbstractInsnNode) o;
+ }
+
+ public void set(Object o) {
+ InsnList.this.set(next.prev, (AbstractInsnNode) o);
+ prev = (AbstractInsnNode) o;
+ }
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnNode.java
new file mode 100644
index 0000000..234504f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/InsnNode.java
@@ -0,0 +1,81 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a zero operand instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class InsnNode extends AbstractInsnNode {
+
+ /**
+ * Constructs a new {@link InsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This
+ * opcode must be NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
+ * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
+ * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD, LALOAD,
+ * FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IASTORE, LASTORE,
+ * FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE, POP, POP2,
+ * DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP, IADD, LADD,
+ * FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, INEG, LNEG, FNEG, DNEG,
+ * ISHL, LSHL, ISHR, LSHR, IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR,
+ * LXOR, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F,
+ * I2B, I2C, I2S, LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN,
+ * FRETURN, DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW,
+ * MONITORENTER, or MONITOREXIT.
+ */
+ public InsnNode(final int opcode) {
+ super(opcode);
+ }
+
+ public int getType() {
+ return INSN;
+ }
+
+ /**
+ * Makes the given visitor visit this instruction.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitInsn(opcode);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new InsnNode(opcode);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IntInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IntInsnNode.java
new file mode 100644
index 0000000..ca67fd0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/IntInsnNode.java
@@ -0,0 +1,81 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents an instruction with a single int operand.
+ *
+ * @author Eric Bruneton
+ */
+public class IntInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction.
+ */
+ public int operand;
+
+ /**
+ * Constructs a new {@link IntInsnNode}.
+ *
+ * @param opcode the opcode of the instruction to be constructed. This
+ * opcode must be BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand the operand of the instruction to be constructed.
+ */
+ public IntInsnNode(final int opcode, final int operand) {
+ super(opcode);
+ this.operand = operand;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be BIPUSH,
+ * SIPUSH or NEWARRAY.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return INT_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitIntInsn(opcode, operand);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new IntInsnNode(opcode, operand);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/JumpInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/JumpInsnNode.java
new file mode 100644
index 0000000..0320e4f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/JumpInsnNode.java
@@ -0,0 +1,89 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a jump instruction. A jump instruction is an
+ * instruction that may jump to another instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class JumpInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is a label that designates
+ * the instruction to which this instruction may jump.
+ */
+ public LabelNode label;
+
+ /**
+ * Constructs a new {@link JumpInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ,
+ * IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label the operand of the instruction to be constructed. This
+ * operand is a label that designates the instruction to which the
+ * jump instruction may jump.
+ */
+ public JumpInsnNode(final int opcode, final LabelNode label) {
+ super(opcode);
+ this.label = label;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be IFEQ, IFNE,
+ * IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT,
+ * IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, GOTO, JSR,
+ * IFNULL or IFNONNULL.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return JUMP_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitJumpInsn(opcode, label.getLabel());
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new JumpInsnNode(opcode, clone(label, labels));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LabelNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LabelNode.java
new file mode 100644
index 0000000..08646e4
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LabelNode.java
@@ -0,0 +1,75 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * An {@link AbstractInsnNode} that encapsulates a {@link Label}.
+ */
+public class LabelNode extends AbstractInsnNode {
+
+ private Label label;
+
+ public LabelNode() {
+ super(-1);
+ }
+
+ public LabelNode(final Label label) {
+ super(-1);
+ this.label = label;
+ }
+
+ public int getType() {
+ return LABEL;
+ }
+
+ public Label getLabel() {
+ if (label == null) {
+ label = new Label();
+ }
+ return label;
+ }
+
+ public void accept(final MethodVisitor cv) {
+ cv.visitLabel(getLabel());
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return (LabelNode) labels.get(this);
+ }
+
+ public void resetLabel() {
+ label = null;
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LdcInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LdcInsnNode.java
new file mode 100644
index 0000000..1f1d138
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LdcInsnNode.java
@@ -0,0 +1,74 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.Map;
+
+/**
+ * A node that represents an LDC instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class LdcInsnNode extends AbstractInsnNode {
+
+ /**
+ * The constant to be loaded on the stack. This parameter must be a non null
+ * {@link Integer}, a {@link Float}, a {@link Long}, a {@link Double}, a
+ * {@link String} or a {@link org.powermock.api.mockito.repackaged.asm.Type}.
+ */
+ public Object cst;
+
+ /**
+ * Constructs a new {@link LdcInsnNode}.
+ *
+ * @param cst the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String}.
+ */
+ public LdcInsnNode(final Object cst) {
+ super(Opcodes.LDC);
+ this.cst = cst;
+ }
+
+ public int getType() {
+ return LDC_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitLdcInsn(cst);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new LdcInsnNode(cst);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LineNumberNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LineNumberNode.java
new file mode 100644
index 0000000..5195354
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LineNumberNode.java
@@ -0,0 +1,79 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a line number declaration. These nodes are pseudo
+ * instruction nodes in order to be inserted in an instruction list.
+ *
+ * @author Eric Bruneton
+ */
+public class LineNumberNode extends AbstractInsnNode {
+
+ /**
+ * A line number. This number refers to the source file from which the class
+ * was compiled.
+ */
+ public int line;
+
+ /**
+ * The first instruction corresponding to this line number.
+ */
+ public LabelNode start;
+
+ /**
+ * Constructs a new {@link LineNumberNode}.
+ *
+ * @param line a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start the first instruction corresponding to this line number.
+ */
+ public LineNumberNode(final int line, final LabelNode start) {
+ super(-1);
+ this.line = line;
+ this.start = start;
+ }
+
+ public int getType() {
+ return LINE;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitLineNumber(line, start.getLabel());
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new LineNumberNode(line, clone(start, labels));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LocalVariableNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LocalVariableNode.java
new file mode 100644
index 0000000..b8a8218
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LocalVariableNode.java
@@ -0,0 +1,115 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+/**
+ * A node that represents a local variable declaration.
+ *
+ * @author Eric Bruneton
+ */
+public class LocalVariableNode {
+
+ /**
+ * The name of a local variable.
+ */
+ public String name;
+
+ /**
+ * The type descriptor of this local variable.
+ */
+ public String desc;
+
+ /**
+ * The signature of this local variable. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The first instruction corresponding to the scope of this local variable
+ * (inclusive).
+ */
+ public LabelNode start;
+
+ /**
+ * The last instruction corresponding to the scope of this local variable
+ * (exclusive).
+ */
+ public LabelNode end;
+
+ /**
+ * The local variable's index.
+ */
+ public int index;
+
+ /**
+ * Constructs a new {@link LocalVariableNode}.
+ *
+ * @param name the name of a local variable.
+ * @param desc the type descriptor of this local variable.
+ * @param signature the signature of this local variable. May be
+ * <tt>null</tt>.
+ * @param start the first instruction corresponding to the scope of this
+ * local variable (inclusive).
+ * @param end the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index the local variable's index.
+ */
+ public LocalVariableNode(
+ final String name,
+ final String desc,
+ final String signature,
+ final LabelNode start,
+ final LabelNode end,
+ final int index)
+ {
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.start = start;
+ this.end = end;
+ this.index = index;
+ }
+
+ /**
+ * Makes the given visitor visit this local variable declaration.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitLocalVariable(name,
+ desc,
+ signature,
+ start.getLabel(),
+ end.getLabel(),
+ index);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LookupSwitchInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LookupSwitchInsnNode.java
new file mode 100644
index 0000000..27dff0e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/LookupSwitchInsnNode.java
@@ -0,0 +1,113 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A node that represents a LOOKUPSWITCH instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class LookupSwitchInsnNode extends AbstractInsnNode {
+
+ /**
+ * Beginning of the default handler block.
+ */
+ public LabelNode dflt;
+
+ /**
+ * The values of the keys. This list is a list of {@link Integer} objects.
+ */
+ public List keys;
+
+ /**
+ * Beginnings of the handler blocks. This list is a list of
+ * {@link LabelNode} objects.
+ */
+ public List labels;
+
+ /**
+ * Constructs a new {@link LookupSwitchInsnNode}.
+ *
+ * @param dflt beginning of the default handler block.
+ * @param keys the values of the keys.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>keys[i]</tt> key.
+ */
+ public LookupSwitchInsnNode(
+ final LabelNode dflt,
+ final int[] keys,
+ final LabelNode[] labels)
+ {
+ super(Opcodes.LOOKUPSWITCH);
+ this.dflt = dflt;
+ this.keys = new ArrayList(keys == null ? 0 : keys.length);
+ this.labels = new ArrayList(labels == null ? 0 : labels.length);
+ if (keys != null) {
+ for (int i = 0; i < keys.length; ++i) {
+ this.keys.add(new Integer(keys[i]));
+ }
+ }
+ if (labels != null) {
+ this.labels.addAll(Arrays.asList(labels));
+ }
+ }
+
+ public int getType() {
+ return LOOKUPSWITCH_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ int[] keys = new int[this.keys.size()];
+ for (int i = 0; i < keys.length; ++i) {
+ keys[i] = ((Integer) this.keys.get(i)).intValue();
+ }
+ Label[] labels = new Label[this.labels.size()];
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i] = ((LabelNode) this.labels.get(i)).getLabel();
+ }
+ mv.visitLookupSwitchInsn(dflt.getLabel(), keys, labels);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ LookupSwitchInsnNode clone = new LookupSwitchInsnNode(clone(dflt,
+ labels), null, clone(this.labels, labels));
+ clone.keys.addAll(keys);
+ return clone;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MemberNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MemberNode.java
new file mode 100644
index 0000000..fa5465b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MemberNode.java
@@ -0,0 +1,120 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An abstract class, field or method node.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class MemberNode {
+
+ /**
+ * The runtime visible annotations of this class, field or method. This list
+ * is a list of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.AnnotationNode
+ * @label visible
+ */
+ public List visibleAnnotations;
+
+ /**
+ * The runtime invisible annotations of this class, field or method. This
+ * list is a list of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.AnnotationNode
+ * @label invisible
+ */
+ public List invisibleAnnotations;
+
+ /**
+ * The non standard attributes of this class, field or method. This list is
+ * a list of {@link Attribute} objects. May be <tt>null</tt>.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.Attribute
+ */
+ public List attrs;
+
+ /**
+ * Constructs a new {@link MemberNode}.
+ */
+ protected MemberNode() {
+ }
+
+ /**
+ * Visits an annotation of this class, field or method.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleAnnotations == null) {
+ visibleAnnotations = new ArrayList(1);
+ }
+ visibleAnnotations.add(an);
+ } else {
+ if (invisibleAnnotations == null) {
+ invisibleAnnotations = new ArrayList(1);
+ }
+ invisibleAnnotations.add(an);
+ }
+ return an;
+ }
+
+ /**
+ * Visits a non standard attribute of this class, field or method.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(final Attribute attr) {
+ if (attrs == null) {
+ attrs = new ArrayList(1);
+ }
+ attrs.add(attr);
+ }
+
+ /**
+ * Visits the end of this class, field or method.
+ */
+ public void visitEnd() {
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodInsnNode.java
new file mode 100644
index 0000000..136a70c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodInsnNode.java
@@ -0,0 +1,104 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a method instruction. A method instruction is an
+ * instruction that invokes a method.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodInsnNode extends AbstractInsnNode {
+
+ /**
+ * The internal name of the method's owner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ */
+ public String owner;
+
+ /**
+ * The method's name.
+ */
+ public String name;
+
+ /**
+ * The method's descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link MethodInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner the internal name of the method's owner class (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type#getInternalName() getInternalName}).
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public MethodInsnNode(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ super(opcode);
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or INVOKEINTERFACE.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return METHOD_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new MethodInsnNode(opcode, owner, name, desc);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodNode.java
new file mode 100644
index 0000000..028d28c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MethodNode.java
@@ -0,0 +1,490 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A node that represents a method.
+ *
+ * @author Eric Bruneton
+ */
+public class MethodNode extends MemberNode implements MethodVisitor {
+
+ /**
+ * The method's access flags (see {@link Opcodes}). This field also
+ * indicates if the method is synthetic and/or deprecated.
+ */
+ public int access;
+
+ /**
+ * The method's name.
+ */
+ public String name;
+
+ /**
+ * The method's descriptor (see {@link Type}).
+ */
+ public String desc;
+
+ /**
+ * The method's signature. May be <tt>null</tt>.
+ */
+ public String signature;
+
+ /**
+ * The internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). This list is a list of
+ * {@link String} objects.
+ */
+ public List exceptions;
+
+ /**
+ * The default value of this annotation interface method. This field must be
+ * a {@link Byte}, {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer}, {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type}, or an two elements String array (for
+ * enumeration values), a {@link AnnotationNode}, or a {@link List} of
+ * values of one of the preceding types. May be <tt>null</tt>.
+ */
+ public Object annotationDefault;
+
+ /**
+ * The runtime visible parameter annotations of this method. These lists are
+ * lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.AnnotationNode
+ * @label invisible parameters
+ */
+ public List[] visibleParameterAnnotations;
+
+ /**
+ * The runtime invisible parameter annotations of this method. These lists
+ * are lists of {@link AnnotationNode} objects. May be <tt>null</tt>.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.AnnotationNode
+ * @label visible parameters
+ */
+ public List[] invisibleParameterAnnotations;
+
+ /**
+ * The instructions of this method. This list is a list of
+ * {@link AbstractInsnNode} objects.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode
+ * @label instructions
+ */
+ public InsnList instructions;
+
+ /**
+ * The try catch blocks of this method. This list is a list of
+ * {@link TryCatchBlockNode} objects.
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.TryCatchBlockNode
+ */
+ public List tryCatchBlocks;
+
+ /**
+ * The maximum stack size of this method.
+ */
+ public int maxStack;
+
+ /**
+ * The maximum number of local variables of this method.
+ */
+ public int maxLocals;
+
+ /**
+ * The local variables of this method. This list is a list of
+ * {@link LocalVariableNode} objects. May be <tt>null</tt>
+ *
+ * @associates org.powermock.api.mockito.repackaged.asm.tree.LocalVariableNode
+ */
+ public List localVariables;
+
+ /**
+ * Constructs an unitialized {@link MethodNode}.
+ */
+ public MethodNode() {
+ this.instructions = new InsnList();
+ }
+
+ /**
+ * Constructs a new {@link MethodNode}.
+ *
+ * @param access the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name the method's name.
+ * @param desc the method's descriptor (see {@link Type}).
+ * @param signature the method's signature. May be <tt>null</tt>.
+ * @param exceptions the internal names of the method's exception classes
+ * (see {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ public MethodNode(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ this();
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.exceptions = new ArrayList(exceptions == null
+ ? 0
+ : exceptions.length);
+ boolean isAbstract = (access & Opcodes.ACC_ABSTRACT) != 0;
+ if (!isAbstract) {
+ this.localVariables = new ArrayList(5);
+ }
+ this.tryCatchBlocks = new ArrayList();
+ if (exceptions != null) {
+ this.exceptions.addAll(Arrays.asList(exceptions));
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor interface
+ // ------------------------------------------------------------------------
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ return new AnnotationNode(new ArrayList(0) {
+ public boolean add(final Object o) {
+ annotationDefault = o;
+ return super.add(o);
+ }
+ });
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationNode an = new AnnotationNode(desc);
+ if (visible) {
+ if (visibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(this.desc).length;
+ visibleParameterAnnotations = new List[params];
+ }
+ if (visibleParameterAnnotations[parameter] == null) {
+ visibleParameterAnnotations[parameter] = new ArrayList(1);
+ }
+ visibleParameterAnnotations[parameter].add(an);
+ } else {
+ if (invisibleParameterAnnotations == null) {
+ int params = Type.getArgumentTypes(this.desc).length;
+ invisibleParameterAnnotations = new List[params];
+ }
+ if (invisibleParameterAnnotations[parameter] == null) {
+ invisibleParameterAnnotations[parameter] = new ArrayList(1);
+ }
+ invisibleParameterAnnotations[parameter].add(an);
+ }
+ return an;
+ }
+
+ public void visitCode() {
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ instructions.add(new FrameNode(type, nLocal, local == null
+ ? null
+ : getLabelNodes(local), nStack, stack == null
+ ? null
+ : getLabelNodes(stack)));
+ }
+
+ public void visitInsn(final int opcode) {
+ instructions.add(new InsnNode(opcode));
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ instructions.add(new IntInsnNode(opcode, operand));
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ instructions.add(new VarInsnNode(opcode, var));
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ instructions.add(new TypeInsnNode(opcode, type));
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ instructions.add(new FieldInsnNode(opcode, owner, name, desc));
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ instructions.add(new MethodInsnNode(opcode, owner, name, desc));
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ instructions.add(new JumpInsnNode(opcode, getLabelNode(label)));
+ }
+
+ public void visitLabel(final Label label) {
+ instructions.add(getLabelNode(label));
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ instructions.add(new LdcInsnNode(cst));
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ instructions.add(new IincInsnNode(var, increment));
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ instructions.add(new TableSwitchInsnNode(min,
+ max,
+ getLabelNode(dflt),
+ getLabelNodes(labels)));
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ instructions.add(new LookupSwitchInsnNode(getLabelNode(dflt),
+ keys,
+ getLabelNodes(labels)));
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ instructions.add(new MultiANewArrayInsnNode(desc, dims));
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ tryCatchBlocks.add(new TryCatchBlockNode(getLabelNode(start),
+ getLabelNode(end),
+ getLabelNode(handler),
+ type));
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ localVariables.add(new LocalVariableNode(name,
+ desc,
+ signature,
+ getLabelNode(start),
+ getLabelNode(end),
+ index));
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ instructions.add(new LineNumberNode(line, getLabelNode(start)));
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+
+ /**
+ * Returns the LabelNode corresponding to the given Label. Creates a new
+ * LabelNode if necessary. The default implementation of this method uses
+ * the {@link Label#info} field to store associations between labels and
+ * label nodes.
+ *
+ * @param l a Label.
+ * @return the LabelNode corresponding to l.
+ */
+ protected LabelNode getLabelNode(final Label l) {
+ if (!(l.info instanceof LabelNode)) {
+ l.info = new LabelNode(l);
+ }
+ return (LabelNode) l.info;
+ }
+
+ private LabelNode[] getLabelNodes(final Label[] l) {
+ LabelNode[] nodes = new LabelNode[l.length];
+ for (int i = 0; i < l.length; ++i) {
+ nodes[i] = getLabelNode(l[i]);
+ }
+ return nodes;
+ }
+
+ private Object[] getLabelNodes(final Object[] objs) {
+ Object[] nodes = new Object[objs.length];
+ for (int i = 0; i < objs.length; ++i) {
+ Object o = objs[i];
+ if (o instanceof Label) {
+ o = getLabelNode((Label) o);
+ }
+ nodes[i] = o;
+ }
+ return nodes;
+ }
+
+ // ------------------------------------------------------------------------
+ // Accept method
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given class visitor visit this method.
+ *
+ * @param cv a class visitor.
+ */
+ public void accept(final ClassVisitor cv) {
+ String[] exceptions = new String[this.exceptions.size()];
+ this.exceptions.toArray(exceptions);
+ MethodVisitor mv = cv.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions);
+ if (mv != null) {
+ accept(mv);
+ }
+ }
+
+ /**
+ * Makes the given method visitor visit this method.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ // visits the method attributes
+ int i, j, n;
+ if (annotationDefault != null) {
+ AnnotationVisitor av = mv.visitAnnotationDefault();
+ AnnotationNode.accept(av, null, annotationDefault);
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) visibleAnnotations.get(i);
+ an.accept(mv.visitAnnotation(an.desc, true));
+ }
+ n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
+ for (i = 0; i < n; ++i) {
+ AnnotationNode an = (AnnotationNode) invisibleAnnotations.get(i);
+ an.accept(mv.visitAnnotation(an.desc, false));
+ }
+ n = visibleParameterAnnotations == null
+ ? 0
+ : visibleParameterAnnotations.length;
+ for (i = 0; i < n; ++i) {
+ List l = visibleParameterAnnotations[i];
+ if (l == null) {
+ continue;
+ }
+ for (j = 0; j < l.size(); ++j) {
+ AnnotationNode an = (AnnotationNode) l.get(j);
+ an.accept(mv.visitParameterAnnotation(i, an.desc, true));
+ }
+ }
+ n = invisibleParameterAnnotations == null
+ ? 0
+ : invisibleParameterAnnotations.length;
+ for (i = 0; i < n; ++i) {
+ List l = invisibleParameterAnnotations[i];
+ if (l == null) {
+ continue;
+ }
+ for (j = 0; j < l.size(); ++j) {
+ AnnotationNode an = (AnnotationNode) l.get(j);
+ an.accept(mv.visitParameterAnnotation(i, an.desc, false));
+ }
+ }
+ n = attrs == null ? 0 : attrs.size();
+ for (i = 0; i < n; ++i) {
+ mv.visitAttribute((Attribute) attrs.get(i));
+ }
+ // visits the method's code
+ if (instructions.size() > 0) {
+ mv.visitCode();
+ // visits try catch blocks
+ for (i = 0; i < tryCatchBlocks.size(); ++i) {
+ ((TryCatchBlockNode) tryCatchBlocks.get(i)).accept(mv);
+ }
+ // visits instructions
+ instructions.accept(mv);
+ // visits local variables
+ n = localVariables == null ? 0 : localVariables.size();
+ for (i = 0; i < n; ++i) {
+ ((LocalVariableNode) localVariables.get(i)).accept(mv);
+ }
+ // visits maxs
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+ mv.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MultiANewArrayInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MultiANewArrayInsnNode.java
new file mode 100644
index 0000000..0e114f2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/MultiANewArrayInsnNode.java
@@ -0,0 +1,78 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.Map;
+
+/**
+ * A node that represents a MULTIANEWARRAY instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class MultiANewArrayInsnNode extends AbstractInsnNode {
+
+ /**
+ * An array type descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Number of dimensions of the array to allocate.
+ */
+ public int dims;
+
+ /**
+ * Constructs a new {@link MultiANewArrayInsnNode}.
+ *
+ * @param desc an array type descriptor (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ * @param dims number of dimensions of the array to allocate.
+ */
+ public MultiANewArrayInsnNode(final String desc, final int dims) {
+ super(Opcodes.MULTIANEWARRAY);
+ this.desc = desc;
+ this.dims = dims;
+ }
+
+ public int getType() {
+ return MULTIANEWARRAY_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new MultiANewArrayInsnNode(desc, dims);
+ }
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TableSwitchInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TableSwitchInsnNode.java
new file mode 100644
index 0000000..ee23afa
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TableSwitchInsnNode.java
@@ -0,0 +1,112 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A node that represents a TABLESWITCH instruction.
+ *
+ * @author Eric Bruneton
+ */
+public class TableSwitchInsnNode extends AbstractInsnNode {
+
+ /**
+ * The minimum key value.
+ */
+ public int min;
+
+ /**
+ * The maximum key value.
+ */
+ public int max;
+
+ /**
+ * Beginning of the default handler block.
+ */
+ public LabelNode dflt;
+
+ /**
+ * Beginnings of the handler blocks. This list is a list of
+ * {@link LabelNode} objects.
+ */
+ public List labels;
+
+ /**
+ * Constructs a new {@link TableSwitchInsnNode}.
+ *
+ * @param min the minimum key value.
+ * @param max the maximum key value.
+ * @param dflt beginning of the default handler block.
+ * @param labels beginnings of the handler blocks. <tt>labels[i]</tt> is
+ * the beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public TableSwitchInsnNode(
+ final int min,
+ final int max,
+ final LabelNode dflt,
+ final LabelNode[] labels)
+ {
+ super(Opcodes.TABLESWITCH);
+ this.min = min;
+ this.max = max;
+ this.dflt = dflt;
+ this.labels = new ArrayList();
+ if (labels != null) {
+ this.labels.addAll(Arrays.asList(labels));
+ }
+ }
+
+ public int getType() {
+ return TABLESWITCH_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ Label[] labels = new Label[this.labels.size()];
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i] = ((LabelNode) this.labels.get(i)).getLabel();
+ }
+ mv.visitTableSwitchInsn(min, max, dflt.getLabel(), labels);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new TableSwitchInsnNode(min,
+ max,
+ clone(dflt, labels),
+ clone(this.labels, labels));
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TryCatchBlockNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TryCatchBlockNode.java
new file mode 100644
index 0000000..0a598dd
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TryCatchBlockNode.java
@@ -0,0 +1,94 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+/**
+ * A node that represents a try catch block.
+ *
+ * @author Eric Bruneton
+ */
+public class TryCatchBlockNode {
+
+ /**
+ * Beginning of the exception handler's scope (inclusive).
+ */
+ public LabelNode start;
+
+ /**
+ * End of the exception handler's scope (exclusive).
+ */
+ public LabelNode end;
+
+ /**
+ * Beginning of the exception handler's code.
+ */
+ public LabelNode handler;
+
+ /**
+ * Internal name of the type of exceptions handled by the handler. May be
+ * <tt>null</tt> to catch any exceptions (for "finally" blocks).
+ */
+ public String type;
+
+ /**
+ * Constructs a new {@link TryCatchBlockNode}.
+ *
+ * @param start beginning of the exception handler's scope (inclusive).
+ * @param end end of the exception handler's scope (exclusive).
+ * @param handler beginning of the exception handler's code.
+ * @param type internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for "finally"
+ * blocks).
+ */
+ public TryCatchBlockNode(
+ final LabelNode start,
+ final LabelNode end,
+ final LabelNode handler,
+ final String type)
+ {
+ this.start = start;
+ this.end = end;
+ this.handler = handler;
+ this.type = type;
+ }
+
+ /**
+ * Makes the given visitor visit this try catch block.
+ *
+ * @param mv a method visitor.
+ */
+ public void accept(final MethodVisitor mv) {
+ mv.visitTryCatchBlock(start.getLabel(), end.getLabel(), handler == null
+ ? null
+ : handler.getLabel(), type);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TypeInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TypeInsnNode.java
new file mode 100644
index 0000000..6e65732
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/TypeInsnNode.java
@@ -0,0 +1,84 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a type instruction. A type instruction is an
+ * instruction that takes a type descriptor as parameter.
+ *
+ * @author Eric Bruneton
+ */
+public class TypeInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is an internal name (see
+ * {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public String desc;
+
+ /**
+ * Constructs a new {@link TypeInsnNode}.
+ *
+ * @param opcode the opcode of the type instruction to be constructed. This
+ * opcode must be NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param desc the operand of the instruction to be constructed. This
+ * operand is an internal name (see {@link org.powermock.api.mockito.repackaged.asm.Type}).
+ */
+ public TypeInsnNode(final int opcode, final String desc) {
+ super(opcode);
+ this.desc = desc;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be NEW,
+ * ANEWARRAY, CHECKCAST or INSTANCEOF.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return TYPE_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitTypeInsn(opcode, desc);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new TypeInsnNode(opcode, desc);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/VarInsnNode.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/VarInsnNode.java
new file mode 100644
index 0000000..4c5f76a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/VarInsnNode.java
@@ -0,0 +1,87 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree;
+
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+import java.util.Map;
+
+/**
+ * A node that represents a local variable instruction. A local variable
+ * instruction is an instruction that loads or stores the value of a local
+ * variable.
+ *
+ * @author Eric Bruneton
+ */
+public class VarInsnNode extends AbstractInsnNode {
+
+ /**
+ * The operand of this instruction. This operand is the index of a local
+ * variable.
+ */
+ public int var;
+
+ /**
+ * Constructs a new {@link VarInsnNode}.
+ *
+ * @param opcode the opcode of the local variable instruction to be
+ * constructed. This opcode must be ILOAD, LLOAD, FLOAD, DLOAD,
+ * ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var the operand of the instruction to be constructed. This operand
+ * is the index of a local variable.
+ */
+ public VarInsnNode(final int opcode, final int var) {
+ super(opcode);
+ this.var = var;
+ }
+
+ /**
+ * Sets the opcode of this instruction.
+ *
+ * @param opcode the new instruction opcode. This opcode must be ILOAD,
+ * LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE, ASTORE
+ * or RET.
+ */
+ public void setOpcode(final int opcode) {
+ this.opcode = opcode;
+ }
+
+ public int getType() {
+ return VAR_INSN;
+ }
+
+ public void accept(final MethodVisitor mv) {
+ mv.visitVarInsn(opcode, var);
+ }
+
+ public AbstractInsnNode clone(final Map labels) {
+ return new VarInsnNode(opcode, var);
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Analyzer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Analyzer.java
new file mode 100644
index 0000000..02d312a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Analyzer.java
@@ -0,0 +1,507 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.IincInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.InsnList;
+import org.powermock.api.mockito.repackaged.asm.tree.JumpInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.LabelNode;
+import org.powermock.api.mockito.repackaged.asm.tree.LookupSwitchInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodNode;
+import org.powermock.api.mockito.repackaged.asm.tree.TableSwitchInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.TryCatchBlockNode;
+import org.powermock.api.mockito.repackaged.asm.tree.VarInsnNode;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A semantic bytecode analyzer. <i>This class does not fully check that JSR and
+ * RET instructions are valid.</i>
+ *
+ * @author Eric Bruneton
+ */
+public class Analyzer implements Opcodes {
+
+ private final Interpreter interpreter;
+
+ private int n;
+
+ private InsnList insns;
+
+ private List[] handlers;
+
+ private Frame[] frames;
+
+ private Subroutine[] subroutines;
+
+ private boolean[] queued;
+
+ private int[] queue;
+
+ private int top;
+
+ /**
+ * Constructs a new {@link Analyzer}.
+ *
+ * @param interpreter the interpreter to be used to symbolically interpret
+ * the bytecode instructions.
+ */
+ public Analyzer(final Interpreter interpreter) {
+ this.interpreter = interpreter;
+ }
+
+ /**
+ * Analyzes the given method.
+ *
+ * @param owner the internal name of the class to which the method belongs.
+ * @param m the method to be analyzed.
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if and only if the corresponding
+ * instruction cannot be reached (dead code).
+ * @throws AnalyzerException if a problem occurs during the analysis.
+ */
+ public Frame[] analyze(final String owner, final MethodNode m)
+ throws AnalyzerException
+ {
+ if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0) {
+ frames = new Frame[0];
+ return frames;
+ }
+ n = m.instructions.size();
+ insns = m.instructions;
+ handlers = new List[n];
+ frames = new Frame[n];
+ subroutines = new Subroutine[n];
+ queued = new boolean[n];
+ queue = new int[n];
+ top = 0;
+
+ // computes exception handlers for each instruction
+ for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
+ TryCatchBlockNode tcb = (TryCatchBlockNode) m.tryCatchBlocks.get(i);
+ int begin = insns.indexOf(tcb.start);
+ int end = insns.indexOf(tcb.end);
+ for (int j = begin; j < end; ++j) {
+ List insnHandlers = handlers[j];
+ if (insnHandlers == null) {
+ insnHandlers = new ArrayList();
+ handlers[j] = insnHandlers;
+ }
+ insnHandlers.add(tcb);
+ }
+ }
+
+ // computes the subroutine for each instruction:
+ Subroutine main = new Subroutine(null, m.maxLocals, null);
+ List subroutineCalls = new ArrayList();
+ Map subroutineHeads = new HashMap();
+ findSubroutine(0, main, subroutineCalls);
+ while (!subroutineCalls.isEmpty()) {
+ JumpInsnNode jsr = (JumpInsnNode) subroutineCalls.remove(0);
+ Subroutine sub = (Subroutine) subroutineHeads.get(jsr.label);
+ if (sub == null) {
+ sub = new Subroutine(jsr.label, m.maxLocals, jsr);
+ subroutineHeads.put(jsr.label, sub);
+ findSubroutine(insns.indexOf(jsr.label), sub, subroutineCalls);
+ } else {
+ sub.callers.add(jsr);
+ }
+ }
+ for (int i = 0; i < n; ++i) {
+ if (subroutines[i] != null && subroutines[i].start == null) {
+ subroutines[i] = null;
+ }
+ }
+
+ // initializes the data structures for the control flow analysis
+ Frame current = newFrame(m.maxLocals, m.maxStack);
+ Frame handler = newFrame(m.maxLocals, m.maxStack);
+ Type[] args = Type.getArgumentTypes(m.desc);
+ int local = 0;
+ if ((m.access & ACC_STATIC) == 0) {
+ Type ctype = Type.getObjectType(owner);
+ current.setLocal(local++, interpreter.newValue(ctype));
+ }
+ for (int i = 0; i < args.length; ++i) {
+ current.setLocal(local++, interpreter.newValue(args[i]));
+ if (args[i].getSize() == 2) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ }
+ while (local < m.maxLocals) {
+ current.setLocal(local++, interpreter.newValue(null));
+ }
+ merge(0, current, null);
+
+ // control flow analysis
+ while (top > 0) {
+ int insn = queue[--top];
+ Frame f = frames[insn];
+ Subroutine subroutine = subroutines[insn];
+ queued[insn] = false;
+
+ try {
+ AbstractInsnNode insnNode = m.instructions.get(insn);
+ int insnOpcode = insnNode.getOpcode();
+ int insnType = insnNode.getType();
+
+ if (insnType == AbstractInsnNode.LABEL
+ || insnType == AbstractInsnNode.LINE
+ || insnType == AbstractInsnNode.FRAME)
+ {
+ merge(insn + 1, f, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ } else {
+ current.init(f).execute(insnNode, interpreter);
+ subroutine = subroutine == null ? null : subroutine.copy();
+
+ if (insnNode instanceof JumpInsnNode) {
+ JumpInsnNode j = (JumpInsnNode) insnNode;
+ if (insnOpcode != GOTO && insnOpcode != JSR) {
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ int jump = insns.indexOf(j.label);
+ if (insnOpcode == JSR) {
+ merge(jump, current, new Subroutine(j.label,
+ m.maxLocals,
+ j));
+ } else {
+ merge(jump, current, subroutine);
+ }
+ newControlFlowEdge(insn, jump);
+ } else if (insnNode instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(lsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < lsi.labels.size(); ++j) {
+ LabelNode label = (LabelNode) lsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnNode instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
+ int jump = insns.indexOf(tsi.dflt);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ for (int j = 0; j < tsi.labels.size(); ++j) {
+ LabelNode label = (LabelNode) tsi.labels.get(j);
+ jump = insns.indexOf(label);
+ merge(jump, current, subroutine);
+ newControlFlowEdge(insn, jump);
+ }
+ } else if (insnOpcode == RET) {
+ if (subroutine == null) {
+ throw new AnalyzerException("RET instruction outside of a sub routine");
+ }
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ Object caller = subroutine.callers.get(i);
+ int call = insns.indexOf((AbstractInsnNode) caller);
+ if (frames[call] != null) {
+ merge(call + 1,
+ frames[call],
+ current,
+ subroutines[call],
+ subroutine.access);
+ newControlFlowEdge(insn, call + 1);
+ }
+ }
+ } else if (insnOpcode != ATHROW
+ && (insnOpcode < IRETURN || insnOpcode > RETURN))
+ {
+ if (subroutine != null) {
+ if (insnNode instanceof VarInsnNode) {
+ int var = ((VarInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ if (insnOpcode == LLOAD || insnOpcode == DLOAD
+ || insnOpcode == LSTORE
+ || insnOpcode == DSTORE)
+ {
+ subroutine.access[var + 1] = true;
+ }
+ } else if (insnNode instanceof IincInsnNode) {
+ int var = ((IincInsnNode) insnNode).var;
+ subroutine.access[var] = true;
+ }
+ }
+ merge(insn + 1, current, subroutine);
+ newControlFlowEdge(insn, insn + 1);
+ }
+ }
+
+ List insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i);
+ Type type;
+ if (tcb.type == null) {
+ type = Type.getObjectType("java/lang/Throwable");
+ } else {
+ type = Type.getObjectType(tcb.type);
+ }
+ int jump = insns.indexOf(tcb.handler);
+ if (newControlFlowExceptionEdge(insn, jump)) {
+ handler.init(f);
+ handler.clearStack();
+ handler.push(interpreter.newValue(type));
+ merge(jump, handler, subroutine);
+ }
+ }
+ }
+ } catch (AnalyzerException e) {
+ throw new AnalyzerException("Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ } catch (Exception e) {
+ throw new AnalyzerException("Error at instruction " + insn
+ + ": " + e.getMessage(), e);
+ }
+ }
+
+ return frames;
+ }
+
+ private void findSubroutine(int insn, final Subroutine sub, final List calls)
+ throws AnalyzerException
+ {
+ while (true) {
+ if (insn < 0 || insn >= n) {
+ throw new AnalyzerException("Execution can fall off end of the code");
+ }
+ if (subroutines[insn] != null) {
+ return;
+ }
+ subroutines[insn] = sub.copy();
+ AbstractInsnNode node = insns.get(insn);
+
+ // calls findSubroutine recursively on normal successors
+ if (node instanceof JumpInsnNode) {
+ if (node.getOpcode() == JSR) {
+ // do not follow a JSR, it leads to another subroutine!
+ calls.add(node);
+ } else {
+ JumpInsnNode jnode = (JumpInsnNode) node;
+ findSubroutine(insns.indexOf(jnode.label), sub, calls);
+ }
+ } else if (node instanceof TableSwitchInsnNode) {
+ TableSwitchInsnNode tsnode = (TableSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(tsnode.dflt), sub, calls);
+ for (int i = tsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = (LabelNode) tsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ } else if (node instanceof LookupSwitchInsnNode) {
+ LookupSwitchInsnNode lsnode = (LookupSwitchInsnNode) node;
+ findSubroutine(insns.indexOf(lsnode.dflt), sub, calls);
+ for (int i = lsnode.labels.size() - 1; i >= 0; --i) {
+ LabelNode l = (LabelNode) lsnode.labels.get(i);
+ findSubroutine(insns.indexOf(l), sub, calls);
+ }
+ }
+
+ // calls findSubroutine recursively on exception handler successors
+ List insnHandlers = handlers[insn];
+ if (insnHandlers != null) {
+ for (int i = 0; i < insnHandlers.size(); ++i) {
+ TryCatchBlockNode tcb = (TryCatchBlockNode) insnHandlers.get(i);
+ findSubroutine(insns.indexOf(tcb.handler), sub, calls);
+ }
+ }
+
+ // if insn does not falls through to the next instruction, return.
+ switch (node.getOpcode()) {
+ case GOTO:
+ case RET:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case RETURN:
+ case ATHROW:
+ return;
+ }
+ insn++;
+ }
+ }
+
+ /**
+ * Returns the symbolic stack frame for each instruction of the last
+ * recently analyzed method.
+ *
+ * @return the symbolic state of the execution stack frame at each bytecode
+ * instruction of the method. The size of the returned array is
+ * equal to the number of instructions (and labels) of the method. A
+ * given frame is <tt>null</tt> if the corresponding instruction
+ * cannot be reached, or if an error occured during the analysis of
+ * the method.
+ */
+ public Frame[] getFrames() {
+ return frames;
+ }
+
+ /**
+ * Returns the exception handlers for the given instruction.
+ *
+ * @param insn the index of an instruction of the last recently analyzed
+ * method.
+ * @return a list of {@link TryCatchBlockNode} objects.
+ */
+ public List getHandlers(final int insn) {
+ return handlers[insn];
+ }
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals the maximum number of local variables of the frame.
+ * @param nStack the maximum stack size of the frame.
+ * @return the created frame.
+ */
+ protected Frame newFrame(final int nLocals, final int nStack) {
+ return new Frame(nLocals, nStack);
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src a frame.
+ * @return the created frame.
+ */
+ protected Frame newFrame(final Frame src) {
+ return new Frame(src);
+ }
+
+ /**
+ * Creates a control flow graph edge. The default implementation of this
+ * method does nothing. It can be overriden in order to construct the
+ * control flow graph of a method (this method is called by the
+ * {@link #analyze analyze} method during its visit of the method's code).
+ *
+ * @param insn an instruction index.
+ * @param successor index of a successor instruction.
+ */
+ protected void newControlFlowEdge(final int insn, final int successor) {
+ }
+
+ /**
+ * Creates a control flow graph edge corresponding to an exception handler.
+ * The default implementation of this method does nothing. It can be
+ * overriden in order to construct the control flow graph of a method (this
+ * method is called by the {@link #analyze analyze} method during its visit
+ * of the method's code).
+ *
+ * @param insn an instruction index.
+ * @param successor index of a successor instruction.
+ * @return true if this edge must be considered in the data flow analysis
+ * performed by this analyzer, or false otherwise. The default
+ * implementation of this method always returns true.
+ */
+ protected boolean newControlFlowExceptionEdge(
+ final int insn,
+ final int successor)
+ {
+ return true;
+ }
+
+ // -------------------------------------------------------------------------
+
+ private void merge(
+ final int insn,
+ final Frame frame,
+ final Subroutine subroutine) throws AnalyzerException
+ {
+ Frame oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(frame);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(frame, interpreter);
+ }
+
+ if (oldSubroutine == null) {
+ if (subroutine != null) {
+ subroutines[insn] = subroutine.copy();
+ changes = true;
+ }
+ } else {
+ if (subroutine != null) {
+ changes |= oldSubroutine.merge(subroutine);
+ }
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+
+ private void merge(
+ final int insn,
+ final Frame beforeJSR,
+ final Frame afterRET,
+ final Subroutine subroutineBeforeJSR,
+ final boolean[] access) throws AnalyzerException
+ {
+ Frame oldFrame = frames[insn];
+ Subroutine oldSubroutine = subroutines[insn];
+ boolean changes;
+
+ afterRET.merge(beforeJSR, access);
+
+ if (oldFrame == null) {
+ frames[insn] = newFrame(afterRET);
+ changes = true;
+ } else {
+ changes = oldFrame.merge(afterRET, access);
+ }
+
+ if (oldSubroutine != null && subroutineBeforeJSR != null) {
+ changes |= oldSubroutine.merge(subroutineBeforeJSR);
+ }
+ if (changes && !queued[insn]) {
+ queued[insn] = true;
+ queue[top++] = insn;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/AnalyzerException.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/AnalyzerException.java
new file mode 100644
index 0000000..c7ec01e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/AnalyzerException.java
@@ -0,0 +1,56 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+/**
+ * Thrown if a problem occurs during the analysis of a method.
+ *
+ * @author Bing Ran
+ * @author Eric Bruneton
+ */
+public class AnalyzerException extends Exception {
+
+ public AnalyzerException(final String msg) {
+ super(msg);
+ }
+
+ public AnalyzerException(final String msg, final Throwable exception) {
+ super(msg, exception);
+ }
+
+ public AnalyzerException(
+ final String msg,
+ final Object expected,
+ final Value encountered)
+ {
+ super((msg == null ? "Expected " : msg + ": expected ") + expected
+ + ", but found " + encountered);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicInterpreter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicInterpreter.java
new file mode 100644
index 0000000..6feda92
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicInterpreter.java
@@ -0,0 +1,321 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.FieldInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.IntInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.LdcInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MultiANewArrayInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.TypeInsnNode;
+
+import java.util.List;
+
+/**
+ * An {@link Interpreter} for {@link BasicValue} values.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicInterpreter implements Opcodes, Interpreter {
+
+ public Value newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ switch (type.getSort()) {
+ case Type.VOID:
+ return null;
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ case Type.INT:
+ return BasicValue.INT_VALUE;
+ case Type.FLOAT:
+ return BasicValue.FLOAT_VALUE;
+ case Type.LONG:
+ return BasicValue.LONG_VALUE;
+ case Type.DOUBLE:
+ return BasicValue.DOUBLE_VALUE;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return BasicValue.REFERENCE_VALUE;
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ public Value newOperation(final AbstractInsnNode insn) {
+ switch (insn.getOpcode()) {
+ case ACONST_NULL:
+ return newValue(Type.getObjectType("null"));
+ case ICONST_M1:
+ case ICONST_0:
+ case ICONST_1:
+ case ICONST_2:
+ case ICONST_3:
+ case ICONST_4:
+ case ICONST_5:
+ return BasicValue.INT_VALUE;
+ case LCONST_0:
+ case LCONST_1:
+ return BasicValue.LONG_VALUE;
+ case FCONST_0:
+ case FCONST_1:
+ case FCONST_2:
+ return BasicValue.FLOAT_VALUE;
+ case DCONST_0:
+ case DCONST_1:
+ return BasicValue.DOUBLE_VALUE;
+ case BIPUSH:
+ case SIPUSH:
+ return BasicValue.INT_VALUE;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ if (cst instanceof Integer) {
+ return BasicValue.INT_VALUE;
+ } else if (cst instanceof Float) {
+ return BasicValue.FLOAT_VALUE;
+ } else if (cst instanceof Long) {
+ return BasicValue.LONG_VALUE;
+ } else if (cst instanceof Double) {
+ return BasicValue.DOUBLE_VALUE;
+ } else if (cst instanceof Type) {
+ return newValue(Type.getObjectType("java/lang/Class"));
+ } else {
+ return newValue(Type.getType(cst.getClass()));
+ }
+ case JSR:
+ return BasicValue.RETURNADDRESS_VALUE;
+ case GETSTATIC:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEW:
+ return newValue(Type.getObjectType(((TypeInsnNode) insn).desc));
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ return value;
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case L2I:
+ case F2I:
+ case D2I:
+ case I2B:
+ case I2C:
+ case I2S:
+ return BasicValue.INT_VALUE;
+ case FNEG:
+ case I2F:
+ case L2F:
+ case D2F:
+ return BasicValue.FLOAT_VALUE;
+ case LNEG:
+ case I2L:
+ case F2L:
+ case D2L:
+ return BasicValue.LONG_VALUE;
+ case DNEG:
+ case I2D:
+ case L2D:
+ case F2D:
+ return BasicValue.DOUBLE_VALUE;
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case LRETURN:
+ case FRETURN:
+ case DRETURN:
+ case ARETURN:
+ case PUTSTATIC:
+ return null;
+ case GETFIELD:
+ return newValue(Type.getType(((FieldInsnNode) insn).desc));
+ case NEWARRAY:
+ switch (((IntInsnNode) insn).operand) {
+ case T_BOOLEAN:
+ return newValue(Type.getType("[Z"));
+ case T_CHAR:
+ return newValue(Type.getType("[C"));
+ case T_BYTE:
+ return newValue(Type.getType("[B"));
+ case T_SHORT:
+ return newValue(Type.getType("[S"));
+ case T_INT:
+ return newValue(Type.getType("[I"));
+ case T_FLOAT:
+ return newValue(Type.getType("[F"));
+ case T_DOUBLE:
+ return newValue(Type.getType("[D"));
+ case T_LONG:
+ return newValue(Type.getType("[J"));
+ default:
+ throw new AnalyzerException("Invalid array type");
+ }
+ case ANEWARRAY:
+ String desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getType("[" + Type.getObjectType(desc)));
+ case ARRAYLENGTH:
+ return BasicValue.INT_VALUE;
+ case ATHROW:
+ return null;
+ case CHECKCAST:
+ desc = ((TypeInsnNode) insn).desc;
+ return newValue(Type.getObjectType(desc));
+ case INSTANCEOF:
+ return BasicValue.INT_VALUE;
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2) throws AnalyzerException
+ {
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ case BALOAD:
+ case CALOAD:
+ case SALOAD:
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ return BasicValue.INT_VALUE;
+ case FALOAD:
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ return BasicValue.FLOAT_VALUE;
+ case LALOAD:
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ return BasicValue.LONG_VALUE;
+ case DALOAD:
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ return BasicValue.DOUBLE_VALUE;
+ case AALOAD:
+ return BasicValue.REFERENCE_VALUE;
+ case LCMP:
+ case FCMPL:
+ case FCMPG:
+ case DCMPL:
+ case DCMPG:
+ return BasicValue.INT_VALUE;
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ case PUTFIELD:
+ return null;
+ default:
+ throw new Error("Internal error.");
+ }
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3) throws AnalyzerException
+ {
+ return null;
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values)
+ throws AnalyzerException
+ {
+ if (insn.getOpcode() == MULTIANEWARRAY) {
+ return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
+ } else {
+ return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
+ }
+ }
+
+ public Value merge(final Value v, final Value w) {
+ if (!v.equals(w)) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicValue.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicValue.java
new file mode 100644
index 0000000..c2be5d8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicValue.java
@@ -0,0 +1,105 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * A {@link Value} that is represented by its type in a seven types type system.
+ * This type system distinguishes the UNINITIALZED, INT, FLOAT, LONG, DOUBLE,
+ * REFERENCE and RETURNADDRESS types.
+ *
+ * @author Eric Bruneton
+ */
+public class BasicValue implements Value {
+
+ public static final Value UNINITIALIZED_VALUE = new BasicValue(null);
+
+ public static final Value INT_VALUE = new BasicValue(Type.INT_TYPE);
+
+ public static final Value FLOAT_VALUE = new BasicValue(Type.FLOAT_TYPE);
+
+ public static final Value LONG_VALUE = new BasicValue(Type.LONG_TYPE);
+
+ public static final Value DOUBLE_VALUE = new BasicValue(Type.DOUBLE_TYPE);
+
+ public static final Value REFERENCE_VALUE = new BasicValue(Type.getObjectType("java/lang/Object"));
+
+ public static final Value RETURNADDRESS_VALUE = new BasicValue(null);
+
+ private final Type type;
+
+ public BasicValue(final Type type) {
+ this.type = type;
+ }
+
+ public Type getType() {
+ return type;
+ }
+
+ public int getSize() {
+ return type == Type.LONG_TYPE || type == Type.DOUBLE_TYPE ? 2 : 1;
+ }
+
+ public boolean isReference() {
+ return type != null
+ && (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY);
+ }
+
+ public boolean equals(final Object value) {
+ if (value == this) {
+ return true;
+ } else if (value instanceof BasicValue) {
+ if (type == null) {
+ return ((BasicValue) value).type == null;
+ } else {
+ return type.equals(((BasicValue) value).type);
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public int hashCode() {
+ return type == null ? 0 : type.hashCode();
+ }
+
+ public String toString() {
+ if (this == UNINITIALIZED_VALUE) {
+ return ".";
+ } else if (this == RETURNADDRESS_VALUE) {
+ return "A";
+ } else if (this == REFERENCE_VALUE) {
+ return "R";
+ } else {
+ return type.getDescriptor();
+ }
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicVerifier.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicVerifier.java
new file mode 100644
index 0000000..370663f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/BasicVerifier.java
@@ -0,0 +1,423 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.FieldInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodInsnNode;
+
+import java.util.List;
+
+/**
+ * An extended {@link BasicInterpreter} that checks that bytecode instructions
+ * are correctly used.
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class BasicVerifier extends BasicInterpreter {
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case ILOAD:
+ case ISTORE:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FLOAD:
+ case FSTORE:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LLOAD:
+ case LSTORE:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DLOAD:
+ case DSTORE:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case ALOAD:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return value;
+ case ASTORE:
+ if (!((BasicValue) value).isReference()
+ && value != BasicValue.RETURNADDRESS_VALUE)
+ {
+ throw new AnalyzerException(null,
+ "an object reference or a return address",
+ value);
+ }
+ return value;
+ default:
+ return value;
+ }
+ // type is necessarily a primitive type here,
+ // so value must be == to expected value
+ if (value != expected) {
+ throw new AnalyzerException(null, expected, value);
+ }
+ return value;
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+ throws AnalyzerException
+ {
+ Value expected;
+ switch (insn.getOpcode()) {
+ case INEG:
+ case IINC:
+ case I2F:
+ case I2L:
+ case I2D:
+ case I2B:
+ case I2C:
+ case I2S:
+ case IFEQ:
+ case IFNE:
+ case IFLT:
+ case IFGE:
+ case IFGT:
+ case IFLE:
+ case TABLESWITCH:
+ case LOOKUPSWITCH:
+ case IRETURN:
+ case NEWARRAY:
+ case ANEWARRAY:
+ expected = BasicValue.INT_VALUE;
+ break;
+ case FNEG:
+ case F2I:
+ case F2L:
+ case F2D:
+ case FRETURN:
+ expected = BasicValue.FLOAT_VALUE;
+ break;
+ case LNEG:
+ case L2I:
+ case L2F:
+ case L2D:
+ case LRETURN:
+ expected = BasicValue.LONG_VALUE;
+ break;
+ case DNEG:
+ case D2I:
+ case D2F:
+ case D2L:
+ case DRETURN:
+ expected = BasicValue.DOUBLE_VALUE;
+ break;
+ case GETFIELD:
+ expected = newValue(Type.getObjectType(((FieldInsnNode) insn).owner));
+ break;
+ case CHECKCAST:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARRAYLENGTH:
+ if (!isArrayValue(value)) {
+ throw new AnalyzerException(null,
+ "an array reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case ARETURN:
+ case ATHROW:
+ case INSTANCEOF:
+ case MONITORENTER:
+ case MONITOREXIT:
+ case IFNULL:
+ case IFNONNULL:
+ if (!((BasicValue) value).isReference()) {
+ throw new AnalyzerException(null,
+ "an object reference",
+ value);
+ }
+ return super.unaryOperation(insn, value);
+ case PUTSTATIC:
+ expected = newValue(Type.getType(((FieldInsnNode) insn).desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value, expected)) {
+ throw new AnalyzerException(null, expected, value);
+ }
+ return super.unaryOperation(insn, value);
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2) throws AnalyzerException
+ {
+ Value expected1;
+ Value expected2;
+ switch (insn.getOpcode()) {
+ case IALOAD:
+ expected1 = newValue(Type.getType("[I"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case BALOAD:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case CALOAD:
+ expected1 = newValue(Type.getType("[C"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case SALOAD:
+ expected1 = newValue(Type.getType("[S"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case LALOAD:
+ expected1 = newValue(Type.getType("[J"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FALOAD:
+ expected1 = newValue(Type.getType("[F"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DALOAD:
+ expected1 = newValue(Type.getType("[D"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case AALOAD:
+ expected1 = newValue(Type.getType("[Ljava/lang/Object;"));
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case IADD:
+ case ISUB:
+ case IMUL:
+ case IDIV:
+ case IREM:
+ case ISHL:
+ case ISHR:
+ case IUSHR:
+ case IAND:
+ case IOR:
+ case IXOR:
+ case IF_ICMPEQ:
+ case IF_ICMPNE:
+ case IF_ICMPLT:
+ case IF_ICMPGE:
+ case IF_ICMPGT:
+ case IF_ICMPLE:
+ expected1 = BasicValue.INT_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case FADD:
+ case FSUB:
+ case FMUL:
+ case FDIV:
+ case FREM:
+ case FCMPL:
+ case FCMPG:
+ expected1 = BasicValue.FLOAT_VALUE;
+ expected2 = BasicValue.FLOAT_VALUE;
+ break;
+ case LADD:
+ case LSUB:
+ case LMUL:
+ case LDIV:
+ case LREM:
+ case LAND:
+ case LOR:
+ case LXOR:
+ case LCMP:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.LONG_VALUE;
+ break;
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ expected1 = BasicValue.LONG_VALUE;
+ expected2 = BasicValue.INT_VALUE;
+ break;
+ case DADD:
+ case DSUB:
+ case DMUL:
+ case DDIV:
+ case DREM:
+ case DCMPL:
+ case DCMPG:
+ expected1 = BasicValue.DOUBLE_VALUE;
+ expected2 = BasicValue.DOUBLE_VALUE;
+ break;
+ case IF_ACMPEQ:
+ case IF_ACMPNE:
+ expected1 = BasicValue.REFERENCE_VALUE;
+ expected2 = BasicValue.REFERENCE_VALUE;
+ break;
+ case PUTFIELD:
+ FieldInsnNode fin = (FieldInsnNode) insn;
+ expected1 = newValue(Type.getObjectType(fin.owner));
+ expected2 = newValue(Type.getType(fin.desc));
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException("First argument", expected1, value1);
+ } else if (!isSubTypeOf(value2, expected2)) {
+ throw new AnalyzerException("Second argument", expected2, value2);
+ }
+ if (insn.getOpcode() == AALOAD) {
+ return getElementValue(value1);
+ } else {
+ return super.binaryOperation(insn, value1, value2);
+ }
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3) throws AnalyzerException
+ {
+ Value expected1;
+ Value expected3;
+ switch (insn.getOpcode()) {
+ case IASTORE:
+ expected1 = newValue(Type.getType("[I"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case BASTORE:
+ if (isSubTypeOf(value1, newValue(Type.getType("[Z")))) {
+ expected1 = newValue(Type.getType("[Z"));
+ } else {
+ expected1 = newValue(Type.getType("[B"));
+ }
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case CASTORE:
+ expected1 = newValue(Type.getType("[C"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case SASTORE:
+ expected1 = newValue(Type.getType("[S"));
+ expected3 = BasicValue.INT_VALUE;
+ break;
+ case LASTORE:
+ expected1 = newValue(Type.getType("[J"));
+ expected3 = BasicValue.LONG_VALUE;
+ break;
+ case FASTORE:
+ expected1 = newValue(Type.getType("[F"));
+ expected3 = BasicValue.FLOAT_VALUE;
+ break;
+ case DASTORE:
+ expected1 = newValue(Type.getType("[D"));
+ expected3 = BasicValue.DOUBLE_VALUE;
+ break;
+ case AASTORE:
+ expected1 = value1;
+ expected3 = BasicValue.REFERENCE_VALUE;
+ break;
+ default:
+ throw new Error("Internal error.");
+ }
+ if (!isSubTypeOf(value1, expected1)) {
+ throw new AnalyzerException("First argument", "a " + expected1
+ + " array reference", value1);
+ } else if (value2 != BasicValue.INT_VALUE) {
+ throw new AnalyzerException("Second argument",
+ BasicValue.INT_VALUE,
+ value2);
+ } else if (!isSubTypeOf(value3, expected3)) {
+ throw new AnalyzerException("Third argument", expected3, value3);
+ }
+ return null;
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values)
+ throws AnalyzerException
+ {
+ int opcode = insn.getOpcode();
+ if (opcode == MULTIANEWARRAY) {
+ for (int i = 0; i < values.size(); ++i) {
+ if (values.get(i) != BasicValue.INT_VALUE) {
+ throw new AnalyzerException(null,
+ BasicValue.INT_VALUE,
+ (Value) values.get(i));
+ }
+ }
+ } else {
+ int i = 0;
+ int j = 0;
+ if (opcode != INVOKESTATIC) {
+ Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
+ if (!isSubTypeOf((Value) values.get(i++), newValue(owner))) {
+ throw new AnalyzerException("Method owner",
+ newValue(owner),
+ (Value) values.get(0));
+ }
+ }
+ Type[] args = Type.getArgumentTypes(((MethodInsnNode) insn).desc);
+ while (i < values.size()) {
+ Value expected = newValue(args[j++]);
+ Value encountered = (Value) values.get(i++);
+ if (!isSubTypeOf(encountered, expected)) {
+ throw new AnalyzerException("Argument " + j,
+ expected,
+ encountered);
+ }
+ }
+ }
+ return super.naryOperation(insn, values);
+ }
+
+ protected boolean isArrayValue(final Value value) {
+ return ((BasicValue) value).isReference();
+ }
+
+ protected Value getElementValue(final Value objectArrayValue)
+ throws AnalyzerException
+ {
+ return BasicValue.REFERENCE_VALUE;
+ }
+
+ protected boolean isSubTypeOf(final Value value, final Value expected) {
+ return value == expected;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Frame.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Frame.java
new file mode 100644
index 0000000..b2431c4
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Frame.java
@@ -0,0 +1,667 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.IincInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MultiANewArrayInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.VarInsnNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A symbolic execution stack frame. A stack frame contains a set of local
+ * variable slots, and an operand stack. Warning: long and double values are
+ * represented by <i>two</i> slots in local variables, and by <i>one</i> slot
+ * in the operand stack.
+ *
+ * @author Eric Bruneton
+ */
+public class Frame {
+
+ /**
+ * The local variables and operand stack of this frame.
+ */
+ private Value[] values;
+
+ /**
+ * The number of local variables of this frame.
+ */
+ private int locals;
+
+ /**
+ * The number of elements in the operand stack.
+ */
+ private int top;
+
+ /**
+ * Constructs a new frame with the given size.
+ *
+ * @param nLocals the maximum number of local variables of the frame.
+ * @param nStack the maximum stack size of the frame.
+ */
+ public Frame(final int nLocals, final int nStack) {
+ this.values = new Value[nLocals + nStack];
+ this.locals = nLocals;
+ }
+
+ /**
+ * Constructs a new frame that is identical to the given frame.
+ *
+ * @param src a frame.
+ */
+ public Frame(final Frame src) {
+ this(src.locals, src.values.length - src.locals);
+ init(src);
+ }
+
+ /**
+ * Copies the state of the given frame into this frame.
+ *
+ * @param src a frame.
+ * @return this frame.
+ */
+ public Frame init(final Frame src) {
+ System.arraycopy(src.values, 0, values, 0, values.length);
+ top = src.top;
+ return this;
+ }
+
+ /**
+ * Returns the maximum number of local variables of this frame.
+ *
+ * @return the maximum number of local variables of this frame.
+ */
+ public int getLocals() {
+ return locals;
+ }
+
+ /**
+ * Returns the value of the given local variable.
+ *
+ * @param i a local variable index.
+ * @return the value of the given local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public Value getLocal(final int i) throws IndexOutOfBoundsException {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");
+ }
+ return values[i];
+ }
+
+ /**
+ * Sets the value of the given local variable.
+ *
+ * @param i a local variable index.
+ * @param value the new value of this local variable.
+ * @throws IndexOutOfBoundsException if the variable does not exist.
+ */
+ public void setLocal(final int i, final Value value)
+ throws IndexOutOfBoundsException
+ {
+ if (i >= locals) {
+ throw new IndexOutOfBoundsException("Trying to access an inexistant local variable");
+ }
+ values[i] = value;
+ }
+
+ /**
+ * Returns the number of values in the operand stack of this frame. Long and
+ * double values are treated as single values.
+ *
+ * @return the number of values in the operand stack of this frame.
+ */
+ public int getStackSize() {
+ return top;
+ }
+
+ /**
+ * Returns the value of the given operand stack slot.
+ *
+ * @param i the index of an operand stack slot.
+ * @return the value of the given operand stack slot.
+ * @throws IndexOutOfBoundsException if the operand stack slot does not
+ * exist.
+ */
+ public Value getStack(final int i) throws IndexOutOfBoundsException {
+ return values[i + locals];
+ }
+
+ /**
+ * Clears the operand stack of this frame.
+ */
+ public void clearStack() {
+ top = 0;
+ }
+
+ /**
+ * Pops a value from the operand stack of this frame.
+ *
+ * @return the value that has been popped from the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is empty.
+ */
+ public Value pop() throws IndexOutOfBoundsException {
+ if (top == 0) {
+ throw new IndexOutOfBoundsException("Cannot pop operand off an empty stack.");
+ }
+ return values[--top + locals];
+ }
+
+ /**
+ * Pushes a value into the operand stack of this frame.
+ *
+ * @param value the value that must be pushed into the stack.
+ * @throws IndexOutOfBoundsException if the operand stack is full.
+ */
+ public void push(final Value value) throws IndexOutOfBoundsException {
+ if (top + locals >= values.length) {
+ throw new IndexOutOfBoundsException("Insufficient maximum stack size.");
+ }
+ values[top++ + locals] = value;
+ }
+
+ public void execute(
+ final AbstractInsnNode insn,
+ final Interpreter interpreter) throws AnalyzerException
+ {
+ Value value1, value2, value3, value4;
+ List values;
+ int var;
+
+ switch (insn.getOpcode()) {
+ case Opcodes.NOP:
+ break;
+ case Opcodes.ACONST_NULL:
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.LDC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.ILOAD:
+ case Opcodes.LLOAD:
+ case Opcodes.FLOAD:
+ case Opcodes.DLOAD:
+ case Opcodes.ALOAD:
+ push(interpreter.copyOperation(insn,
+ getLocal(((VarInsnNode) insn).var)));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.LALOAD:
+ case Opcodes.FALOAD:
+ case Opcodes.DALOAD:
+ case Opcodes.AALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.LSTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.DSTORE:
+ case Opcodes.ASTORE:
+ value1 = interpreter.copyOperation(insn, pop());
+ var = ((VarInsnNode) insn).var;
+ setLocal(var, value1);
+ if (value1.getSize() == 2) {
+ setLocal(var + 1, interpreter.newValue(null));
+ }
+ if (var > 0) {
+ Value local = getLocal(var - 1);
+ if (local != null && local.getSize() == 2) {
+ setLocal(var - 1, interpreter.newValue(null));
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.LASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.DASTORE:
+ case Opcodes.AASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ value3 = pop();
+ value2 = pop();
+ value1 = pop();
+ interpreter.ternaryOperation(insn, value1, value2, value3);
+ break;
+ case Opcodes.POP:
+ if (pop().getSize() == 2) {
+ throw new AnalyzerException("Illegal use of POP");
+ }
+ break;
+ case Opcodes.POP2:
+ if (pop().getSize() == 1) {
+ if (pop().getSize() != 1) {
+ throw new AnalyzerException("Illegal use of POP2");
+ }
+ }
+ break;
+ case Opcodes.DUP:
+ value1 = pop();
+ if (value1.getSize() != 1) {
+ throw new AnalyzerException("Illegal use of DUP");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X1:
+ value1 = pop();
+ value2 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException("Illegal use of DUP_X1");
+ }
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.DUP_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value3));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ }
+ throw new AnalyzerException("Illegal use of DUP_X2");
+ case Opcodes.DUP2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ throw new AnalyzerException("Illegal use of DUP2");
+ case Opcodes.DUP2_X1:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value3));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ }
+ throw new AnalyzerException("Illegal use of DUP2_X1");
+ case Opcodes.DUP2_X2:
+ value1 = pop();
+ if (value1.getSize() == 1) {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ value4 = pop();
+ if (value4.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value4));
+ push(interpreter.copyOperation(insn, value3));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value3));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ }
+ } else {
+ value2 = pop();
+ if (value2.getSize() == 1) {
+ value3 = pop();
+ if (value3.getSize() == 1) {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value3));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ } else {
+ push(interpreter.copyOperation(insn, value1));
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ }
+ }
+ throw new AnalyzerException("Illegal use of DUP2_X2");
+ case Opcodes.SWAP:
+ value2 = pop();
+ value1 = pop();
+ if (value1.getSize() != 1 || value2.getSize() != 1) {
+ throw new AnalyzerException("Illegal use of SWAP");
+ }
+ push(interpreter.copyOperation(insn, value2));
+ push(interpreter.copyOperation(insn, value1));
+ break;
+ case Opcodes.IADD:
+ case Opcodes.LADD:
+ case Opcodes.FADD:
+ case Opcodes.DADD:
+ case Opcodes.ISUB:
+ case Opcodes.LSUB:
+ case Opcodes.FSUB:
+ case Opcodes.DSUB:
+ case Opcodes.IMUL:
+ case Opcodes.LMUL:
+ case Opcodes.FMUL:
+ case Opcodes.DMUL:
+ case Opcodes.IDIV:
+ case Opcodes.LDIV:
+ case Opcodes.FDIV:
+ case Opcodes.DDIV:
+ case Opcodes.IREM:
+ case Opcodes.LREM:
+ case Opcodes.FREM:
+ case Opcodes.DREM:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ISHL:
+ case Opcodes.LSHL:
+ case Opcodes.ISHR:
+ case Opcodes.LSHR:
+ case Opcodes.IUSHR:
+ case Opcodes.LUSHR:
+ case Opcodes.IAND:
+ case Opcodes.LAND:
+ case Opcodes.IOR:
+ case Opcodes.LOR:
+ case Opcodes.IXOR:
+ case Opcodes.LXOR:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IINC:
+ var = ((IincInsnNode) insn).var;
+ setLocal(var, interpreter.unaryOperation(insn, getLocal(var)));
+ break;
+ case Opcodes.I2L:
+ case Opcodes.I2F:
+ case Opcodes.I2D:
+ case Opcodes.L2I:
+ case Opcodes.L2F:
+ case Opcodes.L2D:
+ case Opcodes.F2I:
+ case Opcodes.F2L:
+ case Opcodes.F2D:
+ case Opcodes.D2I:
+ case Opcodes.D2L:
+ case Opcodes.D2F:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ value2 = pop();
+ value1 = pop();
+ push(interpreter.binaryOperation(insn, value1, value2));
+ break;
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.GOTO:
+ break;
+ case Opcodes.JSR:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.RET:
+ break;
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.IRETURN:
+ case Opcodes.LRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.DRETURN:
+ case Opcodes.ARETURN:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.GETSTATIC:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.PUTSTATIC:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.GETFIELD:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.PUTFIELD:
+ value2 = pop();
+ value1 = pop();
+ interpreter.binaryOperation(insn, value1, value2);
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ values = new ArrayList();
+ String desc = ((MethodInsnNode) insn).desc;
+ for (int i = Type.getArgumentTypes(desc).length; i > 0; --i) {
+ values.add(0, pop());
+ }
+ if (insn.getOpcode() != Opcodes.INVOKESTATIC) {
+ values.add(0, pop());
+ }
+ if (Type.getReturnType(desc) == Type.VOID_TYPE) {
+ interpreter.naryOperation(insn, values);
+ } else {
+ push(interpreter.naryOperation(insn, values));
+ }
+ break;
+ case Opcodes.NEW:
+ push(interpreter.newOperation(insn));
+ break;
+ case Opcodes.NEWARRAY:
+ case Opcodes.ANEWARRAY:
+ case Opcodes.ARRAYLENGTH:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.ATHROW:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.CHECKCAST:
+ case Opcodes.INSTANCEOF:
+ push(interpreter.unaryOperation(insn, pop()));
+ break;
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ case Opcodes.MULTIANEWARRAY:
+ values = new ArrayList();
+ for (int i = ((MultiANewArrayInsnNode) insn).dims; i > 0; --i) {
+ values.add(0, pop());
+ }
+ push(interpreter.naryOperation(insn, values));
+ break;
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ interpreter.unaryOperation(insn, pop());
+ break;
+ default:
+ throw new RuntimeException("Illegal opcode");
+ }
+ }
+
+ /**
+ * Merges this frame with the given frame.
+ *
+ * @param frame a frame.
+ * @param interpreter the interpreter used to merge values.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ * @throws AnalyzerException if the frames have incompatible sizes.
+ */
+ public boolean merge(final Frame frame, final Interpreter interpreter)
+ throws AnalyzerException
+ {
+ if (top != frame.top) {
+ throw new AnalyzerException("Incompatible stack heights");
+ }
+ boolean changes = false;
+ for (int i = 0; i < locals + top; ++i) {
+ Value v = interpreter.merge(values[i], frame.values[i]);
+ if (v != values[i]) {
+ values[i] = v;
+ changes |= true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Merges this frame with the given frame (case of a RET instruction).
+ *
+ * @param frame a frame
+ * @param access the local variables that have been accessed by the
+ * subroutine to which the RET instruction corresponds.
+ * @return <tt>true</tt> if this frame has been changed as a result of the
+ * merge operation, or <tt>false</tt> otherwise.
+ */
+ public boolean merge(final Frame frame, final boolean[] access) {
+ boolean changes = false;
+ for (int i = 0; i < locals; ++i) {
+ if (!access[i] && !values[i].equals(frame.values[i])) {
+ values[i] = frame.values[i];
+ changes = true;
+ }
+ }
+ return changes;
+ }
+
+ /**
+ * Returns a string representation of this frame.
+ *
+ * @return a string representation of this frame.
+ */
+ public String toString() {
+ StringBuffer b = new StringBuffer();
+ for (int i = 0; i < getLocals(); ++i) {
+ b.append(getLocal(i));
+ }
+ b.append(' ');
+ for (int i = 0; i < getStackSize(); ++i) {
+ b.append(getStack(i).toString());
+ }
+ return b.toString();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Interpreter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Interpreter.java
new file mode 100644
index 0000000..18b2de2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Interpreter.java
@@ -0,0 +1,178 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+
+import java.util.List;
+
+/**
+ * A semantic bytecode interpreter. More precisely, this interpreter only
+ * manages the computation of values from other values: it does not manage the
+ * transfer of values to or from the stack, and to or from the local variables.
+ * This separation allows a generic bytecode {@link Analyzer} to work with
+ * various semantic interpreters, without needing to duplicate the code to
+ * simulate the transfer of values.
+ *
+ * @author Eric Bruneton
+ */
+public interface Interpreter {
+
+ /**
+ * Creates a new value that represents the given type.
+ *
+ * Called for method parameters (including <code>this</code>),
+ * exception handler variable and with <code>null</code> type
+ * for variables reserved by long and double types.
+ *
+ * @param type a primitive or reference type, or <tt>null</tt> to
+ * represent an uninitialized value.
+ * @return a value that represents the given type. The size of the returned
+ * value must be equal to the size of the given type.
+ */
+ Value newValue(Type type);
+
+ /**
+ * Interprets a bytecode instruction without arguments. This method is
+ * called for the following opcodes:
+ *
+ * ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
+ * ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
+ * DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value newOperation(AbstractInsnNode insn) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction that moves a value on the stack or to
+ * or from local variables. This method is called for the following opcodes:
+ *
+ * ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
+ * ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the value that must be moved by the instruction.
+ * @return the result of the interpretation of the given instruction. The
+ * returned value must be <tt>equal</tt> to the given value.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value copyOperation(AbstractInsnNode insn, Value value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a single argument. This method is
+ * called for the following opcodes:
+ *
+ * INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
+ * F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
+ * TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
+ * PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
+ * INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value the argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value unaryOperation(AbstractInsnNode insn, Value value)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with two arguments. This method is
+ * called for the following opcodes:
+ *
+ * IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
+ * LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
+ * LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
+ * LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
+ * DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, PUTFIELD
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value binaryOperation(AbstractInsnNode insn, Value value1, Value value2)
+ throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with three arguments. This method is
+ * called for the following opcodes:
+ *
+ * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param value1 the first argument of the instruction to be interpreted.
+ * @param value2 the second argument of the instruction to be interpreted.
+ * @param value3 the third argument of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value ternaryOperation(
+ AbstractInsnNode insn,
+ Value value1,
+ Value value2,
+ Value value3) throws AnalyzerException;
+
+ /**
+ * Interprets a bytecode instruction with a variable number of arguments.
+ * This method is called for the following opcodes:
+ *
+ * INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
+ * MULTIANEWARRAY
+ *
+ * @param insn the bytecode instruction to be interpreted.
+ * @param values the arguments of the instruction to be interpreted.
+ * @return the result of the interpretation of the given instruction.
+ * @throws AnalyzerException if an error occured during the interpretation.
+ */
+ Value naryOperation(AbstractInsnNode insn, List values)
+ throws AnalyzerException;
+
+ /**
+ * Merges two values. The merge operation must return a value that
+ * represents both values (for instance, if the two values are two types,
+ * the merged value must be a common super type of the two types. If the two
+ * values are integer intervals, the merged value must be an interval that
+ * contains the previous ones. Likewise for other types of values).
+ *
+ * @param v a value.
+ * @param w another value.
+ * @return the merged value. If the merged value is equal to <tt>v</tt>,
+ * this method <i>must</i> return <tt>v</tt>.
+ */
+ Value merge(Value v, Value w);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SimpleVerifier.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SimpleVerifier.java
new file mode 100644
index 0000000..1a5ab29
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SimpleVerifier.java
@@ -0,0 +1,284 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.List;
+
+/**
+ * An extended {@link BasicVerifier} that performs more precise verifications.
+ * This verifier computes exact class types, instead of using a single "object
+ * reference" type (as done in the {@link BasicVerifier}).
+ *
+ * @author Eric Bruneton
+ * @author Bing Ran
+ */
+public class SimpleVerifier extends BasicVerifier {
+
+ /**
+ * The class that is verified.
+ */
+ private final Type currentClass;
+
+ /**
+ * The super class of the class that is verified.
+ */
+ private final Type currentSuperClass;
+
+ /**
+ * The interfaces implemented by the class that is verified.
+ */
+ private final List currentClassInterfaces;
+
+ /**
+ * If the class that is verified is an interface.
+ */
+ private final boolean isInterface;
+
+ /**
+ * Constructs a new {@link SimpleVerifier}.
+ */
+ public SimpleVerifier() {
+ this(null, null, false);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass the class that is verified.
+ * @param currentSuperClass the super class of the class that is verified.
+ * @param isInterface if the class that is verified is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass,
+ final Type currentSuperClass,
+ final boolean isInterface)
+ {
+ this(currentClass, currentSuperClass, null, isInterface);
+ }
+
+ /**
+ * Constructs a new {@link SimpleVerifier} to verify a specific class. This
+ * class will not be loaded into the JVM since it may be incorrect.
+ *
+ * @param currentClass the class that is verified.
+ * @param currentSuperClass the super class of the class that is verified.
+ * @param currentClassInterfaces the interfaces implemented by the class
+ * that is verified.
+ * @param isInterface if the class that is verified is an interface.
+ */
+ public SimpleVerifier(
+ final Type currentClass,
+ final Type currentSuperClass,
+ final List currentClassInterfaces,
+ final boolean isInterface)
+ {
+ this.currentClass = currentClass;
+ this.currentSuperClass = currentSuperClass;
+ this.currentClassInterfaces = currentClassInterfaces;
+ this.isInterface = isInterface;
+ }
+
+ public Value newValue(final Type type) {
+ if (type == null) {
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+
+ boolean isArray = type.getSort() == Type.ARRAY;
+ if (isArray) {
+ switch (type.getElementType().getSort()) {
+ case Type.BOOLEAN:
+ case Type.CHAR:
+ case Type.BYTE:
+ case Type.SHORT:
+ return new BasicValue(type);
+ }
+ }
+
+ Value v = super.newValue(type);
+ if (v == BasicValue.REFERENCE_VALUE) {
+ if (isArray) {
+ v = newValue(type.getElementType());
+ String desc = ((BasicValue) v).getType().getDescriptor();
+ for (int i = 0; i < type.getDimensions(); ++i) {
+ desc = '[' + desc;
+ }
+ v = new BasicValue(Type.getType(desc));
+ } else {
+ v = new BasicValue(type);
+ }
+ }
+ return v;
+ }
+
+ protected boolean isArrayValue(final Value value) {
+ Type t = ((BasicValue) value).getType();
+ return t != null
+ && ("Lnull;".equals(t.getDescriptor()) || t.getSort() == Type.ARRAY);
+ }
+
+ protected Value getElementValue(final Value objectArrayValue)
+ throws AnalyzerException
+ {
+ Type arrayType = ((BasicValue) objectArrayValue).getType();
+ if (arrayType != null) {
+ if (arrayType.getSort() == Type.ARRAY) {
+ return newValue(Type.getType(arrayType.getDescriptor()
+ .substring(1)));
+ } else if ("Lnull;".equals(arrayType.getDescriptor())) {
+ return objectArrayValue;
+ }
+ }
+ throw new Error("Internal error");
+ }
+
+ protected boolean isSubTypeOf(final Value value, final Value expected) {
+ Type expectedType = ((BasicValue) expected).getType();
+ Type type = ((BasicValue) value).getType();
+ switch (expectedType.getSort()) {
+ case Type.INT:
+ case Type.FLOAT:
+ case Type.LONG:
+ case Type.DOUBLE:
+ return type == expectedType;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ if ("Lnull;".equals(type.getDescriptor())) {
+ return true;
+ } else if (type.getSort() == Type.OBJECT
+ || type.getSort() == Type.ARRAY)
+ {
+ return isAssignableFrom(expectedType, type);
+ } else {
+ return false;
+ }
+ default:
+ throw new Error("Internal error");
+ }
+ }
+
+ public Value merge(final Value v, final Value w) {
+ if (!v.equals(w)) {
+ Type t = ((BasicValue) v).getType();
+ Type u = ((BasicValue) w).getType();
+ if (t != null
+ && (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY))
+ {
+ if (u != null
+ && (u.getSort() == Type.OBJECT || u.getSort() == Type.ARRAY))
+ {
+ if ("Lnull;".equals(t.getDescriptor())) {
+ return w;
+ }
+ if ("Lnull;".equals(u.getDescriptor())) {
+ return v;
+ }
+ if (isAssignableFrom(t, u)) {
+ return v;
+ }
+ if (isAssignableFrom(u, t)) {
+ return w;
+ }
+ // TODO case of array classes of the same dimension
+ // TODO should we look also for a common super interface?
+ // problem: there may be several possible common super
+ // interfaces
+ do {
+ if (t == null || isInterface(t)) {
+ return BasicValue.REFERENCE_VALUE;
+ }
+ t = getSuperClass(t);
+ if (isAssignableFrom(t, u)) {
+ return newValue(t);
+ }
+ } while (true);
+ }
+ }
+ return BasicValue.UNINITIALIZED_VALUE;
+ }
+ return v;
+ }
+
+ protected boolean isInterface(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return isInterface;
+ }
+ return getClass(t).isInterface();
+ }
+
+ protected Type getSuperClass(final Type t) {
+ if (currentClass != null && t.equals(currentClass)) {
+ return currentSuperClass;
+ }
+ Class c = getClass(t).getSuperclass();
+ return c == null ? null : Type.getType(c);
+ }
+
+ protected boolean isAssignableFrom(final Type t, final Type u) {
+ if (t.equals(u)) {
+ return true;
+ }
+ if (currentClass != null && t.equals(currentClass)) {
+ if (getSuperClass(u) == null) {
+ return false;
+ } else {
+ return isAssignableFrom(t, getSuperClass(u));
+ }
+ }
+ if (currentClass != null && u.equals(currentClass)) {
+ if (isAssignableFrom(t, currentSuperClass)) {
+ return true;
+ }
+ if (currentClassInterfaces != null) {
+ for (int i = 0; i < currentClassInterfaces.size(); ++i) {
+ Type v = (Type) currentClassInterfaces.get(i);
+ if (isAssignableFrom(t, v)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ return getClass(t).isAssignableFrom(getClass(u));
+ }
+
+ protected Class getClass(final Type t) {
+ try {
+ if (t.getSort() == Type.ARRAY) {
+ return Class.forName(t.getDescriptor().replace('/', '.'));
+ }
+ return Class.forName(t.getClassName());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e.toString());
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SmallSet.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SmallSet.java
new file mode 100644
index 0000000..c12867f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SmallSet.java
@@ -0,0 +1,125 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import java.util.AbstractSet;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * A set of at most two elements.
+ *
+ * @author Eric Bruneton
+ */
+class SmallSet extends AbstractSet implements Iterator {
+
+ // if e1 is null, e2 must be null; otherwise e2 must be different from e1
+
+ static final Set EMPTY_SET = new SmallSet(null, null);
+ Object e1, e2;
+
+ SmallSet(final Object e1, final Object e2) {
+ this.e1 = e1;
+ this.e2 = e2;
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of inherited abstract methods
+ // -------------------------------------------------------------------------
+
+ public Iterator iterator() {
+ return new SmallSet(e1, e2);
+ }
+
+ public int size() {
+ return e1 == null ? 0 : (e2 == null ? 1 : 2);
+ }
+
+ // -------------------------------------------------------------------------
+ // Implementation of the Iterator interface
+ // -------------------------------------------------------------------------
+
+ public boolean hasNext() {
+ return e1 != null;
+ }
+
+ public Object next() {
+ Object e = e1;
+ e1 = e2;
+ e2 = null;
+ return e;
+ }
+
+ public void remove() {
+ }
+
+ // -------------------------------------------------------------------------
+ // Utility methods
+ // -------------------------------------------------------------------------
+
+ Set union(final SmallSet s) {
+ if ((s.e1 == e1 && s.e2 == e2) || (s.e1 == e2 && s.e2 == e1)) {
+ return this; // if the two sets are equal, return this
+ }
+ if (s.e1 == null) {
+ return this; // if s is empty, return this
+ }
+ if (e1 == null) {
+ return s; // if this is empty, return s
+ }
+ if (s.e2 == null) { // s contains exactly one element
+ if (e2 == null) {
+ return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+ } else if (s.e1 == e1 || s.e1 == e2) { // s is included in this
+ return this;
+ }
+ }
+ if (e2 == null) { // this contains exactly one element
+ // if (s.e2 == null) { // cannot happen
+ // return new SmallSet(e1, s.e1); // necessarily e1 != s.e1
+ // } else
+ if (e1 == s.e1 || e1 == s.e2) { // this in included in s
+ return s;
+ }
+ }
+ // here we know that there are at least 3 distinct elements
+ HashSet r = new HashSet(4);
+ r.add(e1);
+ if (e2 != null) {
+ r.add(e2);
+ }
+ r.add(s.e1);
+ if (s.e2 != null) {
+ r.add(s.e2);
+ }
+ return r;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceInterpreter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceInterpreter.java
new file mode 100644
index 0000000..7b8c425
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceInterpreter.java
@@ -0,0 +1,174 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.FieldInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.LdcInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodInsnNode;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * An {@link Interpreter} for {@link SourceValue} values.
+ *
+ * @author Eric Bruneton
+ */
+public class SourceInterpreter implements Opcodes, Interpreter {
+
+ public Value newValue(final Type type) {
+ return new SourceValue(type == null ? 1 : type.getSize());
+ }
+
+ public Value newOperation(final AbstractInsnNode insn) {
+ int size;
+ switch (insn.getOpcode()) {
+ case LCONST_0:
+ case LCONST_1:
+ case DCONST_0:
+ case DCONST_1:
+ size = 2;
+ break;
+ case LDC:
+ Object cst = ((LdcInsnNode) insn).cst;
+ size = cst instanceof Long || cst instanceof Double ? 2 : 1;
+ break;
+ case GETSTATIC:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ public Value copyOperation(final AbstractInsnNode insn, final Value value) {
+ return new SourceValue(value.getSize(), insn);
+ }
+
+ public Value unaryOperation(final AbstractInsnNode insn, final Value value)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LNEG:
+ case DNEG:
+ case I2L:
+ case I2D:
+ case L2D:
+ case F2L:
+ case F2D:
+ case D2L:
+ size = 2;
+ break;
+ case GETFIELD:
+ size = Type.getType(((FieldInsnNode) insn).desc).getSize();
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ public Value binaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2)
+ {
+ int size;
+ switch (insn.getOpcode()) {
+ case LALOAD:
+ case DALOAD:
+ case LADD:
+ case DADD:
+ case LSUB:
+ case DSUB:
+ case LMUL:
+ case DMUL:
+ case LDIV:
+ case DDIV:
+ case LREM:
+ case DREM:
+ case LSHL:
+ case LSHR:
+ case LUSHR:
+ case LAND:
+ case LOR:
+ case LXOR:
+ size = 2;
+ break;
+ default:
+ size = 1;
+ }
+ return new SourceValue(size, insn);
+ }
+
+ public Value ternaryOperation(
+ final AbstractInsnNode insn,
+ final Value value1,
+ final Value value2,
+ final Value value3)
+ {
+ return new SourceValue(1, insn);
+ }
+
+ public Value naryOperation(final AbstractInsnNode insn, final List values) {
+ int size;
+ if (insn.getOpcode() == MULTIANEWARRAY) {
+ size = 1;
+ } else {
+ size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
+ }
+ return new SourceValue(size, insn);
+ }
+
+ public Value merge(final Value v, final Value w) {
+ SourceValue dv = (SourceValue) v;
+ SourceValue dw = (SourceValue) w;
+ if (dv.insns instanceof SmallSet && dw.insns instanceof SmallSet) {
+ Set s = ((SmallSet) dv.insns).union((SmallSet) dw.insns);
+ if (s == dv.insns && dv.size == dw.size) {
+ return v;
+ } else {
+ return new SourceValue(Math.min(dv.size, dw.size), s);
+ }
+ }
+ if (dv.size != dw.size || !dv.insns.containsAll(dw.insns)) {
+ Set s = new HashSet();
+ s.addAll(dv.insns);
+ s.addAll(dw.insns);
+ return new SourceValue(Math.min(dv.size, dw.size), s);
+ }
+ return v;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceValue.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceValue.java
new file mode 100644
index 0000000..6a03f36
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/SourceValue.java
@@ -0,0 +1,95 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.tree.AbstractInsnNode;
+
+import java.util.Set;
+
+/**
+ * A {@link Value} that is represented by its type in a two types type system.
+ * This type system distinguishes the ONEWORD and TWOWORDS types.
+ *
+ * @author Eric Bruneton
+ */
+public class SourceValue implements Value {
+
+ /**
+ * The size of this value.
+ */
+ public final int size;
+
+ /**
+ * The instructions that can produce this value. For example, for the Java
+ * code below, the instructions that can produce the value of <tt>i</tt>
+ * at line 5 are the txo ISTORE instructions at line 1 and 3:
+ *
+ * <pre>
+ * 1: i = 0;
+ * 2: if (...) {
+ * 3: i = 1;
+ * 4: }
+ * 5: return i;
+ * </pre>
+ *
+ * This field is a set of {@link AbstractInsnNode} objects.
+ */
+ public final Set insns;
+
+ public SourceValue(final int size) {
+ this(size, SmallSet.EMPTY_SET);
+ }
+
+ public SourceValue(final int size, final AbstractInsnNode insn) {
+ this.size = size;
+ this.insns = new SmallSet(insn, null);
+ }
+
+ public SourceValue(final int size, final Set insns) {
+ this.size = size;
+ this.insns = insns;
+ }
+
+ public int getSize() {
+ return size;
+ }
+
+ public boolean equals(final Object value) {
+ if (!(value instanceof SourceValue)) {
+ return false;
+ }
+ SourceValue v = (SourceValue) value;
+ return size == v.size && insns.equals(v.insns);
+ }
+
+ public int hashCode() {
+ return insns.hashCode();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Subroutine.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Subroutine.java
new file mode 100644
index 0000000..ad416de
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Subroutine.java
@@ -0,0 +1,93 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+import org.powermock.api.mockito.repackaged.asm.tree.JumpInsnNode;
+import org.powermock.api.mockito.repackaged.asm.tree.LabelNode;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A method subroutine (corresponds to a JSR instruction).
+ *
+ * @author Eric Bruneton
+ */
+class Subroutine {
+
+ LabelNode start;
+
+ boolean[] access;
+
+ List callers;
+
+ private Subroutine() {
+ }
+
+ Subroutine(
+ final LabelNode start,
+ final int maxLocals,
+ final JumpInsnNode caller)
+ {
+ this.start = start;
+ this.access = new boolean[maxLocals];
+ this.callers = new ArrayList();
+ callers.add(caller);
+ }
+
+ public Subroutine copy() {
+ Subroutine result = new Subroutine();
+ result.start = start;
+ result.access = new boolean[access.length];
+ System.arraycopy(access, 0, result.access, 0, access.length);
+ result.callers = new ArrayList(callers);
+ return result;
+ }
+
+ public boolean merge(final Subroutine subroutine) throws AnalyzerException {
+ boolean changes = false;
+ for (int i = 0; i < access.length; ++i) {
+ if (subroutine.access[i] && !access[i]) {
+ access[i] = true;
+ changes = true;
+ }
+ }
+ if (subroutine.start == start) {
+ for (int i = 0; i < subroutine.callers.size(); ++i) {
+ Object caller = subroutine.callers.get(i);
+ if (!callers.contains(caller)) {
+ callers.add(caller);
+ changes = true;
+ }
+ }
+ }
+ return changes;
+ }
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Value.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Value.java
new file mode 100644
index 0000000..93720c3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/Value.java
@@ -0,0 +1,45 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.tree.analysis;
+
+/**
+ * An immutable symbolic value for semantic interpretation of bytecode.
+ *
+ * @author Eric Bruneton
+ */
+public interface Value {
+
+ /**
+ * Returns the size of this value in words.
+ *
+ * @return either 1 or 2.
+ */
+ int getSize();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/package.html
new file mode 100644
index 0000000..00656a8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/analysis/package.html
@@ -0,0 +1,97 @@
+<!--
+ ~ ASM: a very small and fast Java bytecode manipulation framework
+ ~ Copyright (c) 2000-2007 INRIA, France Telecom
+ ~ All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions
+ ~ are met:
+ ~ 1. Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ 2. Redistributions in binary form must reproduce the above copyright
+ ~ notice, this list of conditions and the following disclaimer in the
+ ~ documentation and/or other materials provided with the distribution.
+ ~ 3. Neither the name of the copyright holders nor the names of its
+ ~ contributors may be used to endorse or promote products derived from
+ ~ this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ~ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ~ THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+
+<p>
+Provides a framework for static code analysis based on the asm.tree package.
+</p>
+
+<p>
+Basic usage:
+</p>
+
+<pre>
+ClassReader cr = new ClassReader(bytecode);
+ClassNode cn = new ClassNode();
+cr.accept(cn, ClassReader.SKIP_DEBUG);
+
+List methods = cn.methods;
+for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = (MethodNode) methods.get(i);
+ if (method.instructions.size() > 0) {
+ Analyzer a = new Analyzer(new BasicInterpreter());
+ a.analyze(cn.name, method);
+ Frame[] frames = a.getFrames();
+ // Elements of the frames arrray now contains info for each instruction
+ // from the analyzed method. BasicInterpreter creates BasicValue, that
+ // is using simplified type system that distinguishes the UNINITIALZED,
+ // INT, FLOAT, LONG, DOUBLE, REFERENCE and RETURNADDRESS types.
+ ...
+ }
+}
+</pre>
+
+<p>
+ at since ASM 1.4.3
+</p>
+
+</body>
+</html>
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/package.html
new file mode 100644
index 0000000..c89985b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/tree/package.html
@@ -0,0 +1,222 @@
+<!--
+ ~ ASM: a very small and fast Java bytecode manipulation framework
+ ~ Copyright (c) 2000-2007 INRIA, France Telecom
+ ~ All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions
+ ~ are met:
+ ~ 1. Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ 2. Redistributions in binary form must reproduce the above copyright
+ ~ notice, this list of conditions and the following disclaimer in the
+ ~ documentation and/or other materials provided with the distribution.
+ ~ 3. Neither the name of the copyright holders nor the names of its
+ ~ contributors may be used to endorse or promote products derived from
+ ~ this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ~ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ~ THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+
+<p>
+Provides an ASM visitor that constructs a tree representation of the
+classes it visits. This class adapter can be useful to implement "complex"
+class manipulation operations, i.e., operations that would be very hard to
+implement without using a tree representation (such as optimizing the number
+of local variables used by a method).
+</p>
+
+<p>
+However, this class adapter has a cost: it makes ASM bigger and slower. Indeed
+it requires more than twenty new classes, and multiplies the time needed to
+transform a class by almost two (it is almost two times faster to read, "modify"
+and write a class with a ClassAdapter than with a ClassNode). This is why
+this package is bundled in an optional <tt>asm-tree.jar</tt> library that
+is separated from (but requires) the <tt>asm.jar</tt> library, which contains
+the core ASM framework. This is also why <i><font color="red">it is recommended
+not to use this class adapter when it is possible</font></i>.
+</p>
+
+<p>
+The root class is the ClassNode, that can be created from existing bytecode. For example:
+</p>
+
+<pre>
+ ClassReader cr = new ClassReader(source);
+ ClassNode cn = new ClassNode();
+ cr.accept(cn, true);
+</pre>
+
+<p>
+Now content of ClassNode can be modified and then
+serialized back into bytecode:
+</p>
+
+<pre>
+ ClassWriter cw = new ClassWriter(true);
+ cn.accept(cw);
+</pre>
+
+<p>
+Using simple ClassAdapter it is possible to create MethodNode instances per-method.
+In this example MethodNode is acting as a buffer that is flushed out at visitEnd() call:
+</p>
+
+<pre>
+ ClassReader cr = new ClassReader(source);
+ ClassWriter cw = new ClassWriter();
+ ClassAdapter ca = new ClassAdapter(cw) {
+ public MethodVisitor visitMethod(int access, String name,
+ String desc, String signature, String[] exceptions) {
+ final MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions);
+ MethodNode mn = new MethodNode(access, name, desc, signature, exceptions) {
+ public void visitEnd() {
+ // transform or analyze method code using tree API
+ accept(mv);
+ }
+ };
+ }
+ };
+ cr.accept(ca, true);
+</pre>
+
+<p>
+Several strategies can be used to construct method code from scratch. The first
+option is to create a MethodNode, and then create XXXInsnNode instances and
+add them to the instructions list:
+</p>
+
+<pre>
+MethodNode m = new MethodNode(...);
+m.instructions.add(new VarInsnNode(ALOAD, 0));
+...
+</pre>
+
+<p>
+Alternatively, you can use the fact that MethodNode is a MethodVisitor, and use
+that to create the XXXInsnNode and add them to the instructions list through
+the standard MethodVisitor interface:
+</p>
+
+<pre>
+MethodNode m = new MethodNode(...);
+m.visitVarInsn(ALOAD, 0);
+...
+</pre>
+
+<p>
+If you cannot generate all the instructions in sequential order, i.e. if you
+need to save some pointer in the instruction list and then insert instructions
+at that place after other instructions have been generated, you can use InsnList
+methods insert() and insertBefore() to insert instructions at saved pointer.
+</p>
+
+<pre>
+MethodNode m = new MethodNode(...);
+m.visitVarInsn(ALOAD, 0);
+AbstractInsnNode ptr = m.instructions.getLast();
+m.visitVarInsn(ALOAD, 1);
+// inserts an instruction between ALOAD 0 and ALOAD 1
+m.instructions.insert(ptr, new VarInsnNode(ALOAD, 0));
+...
+</pre>
+
+<p>
+If you need to insert instructions while iterating over an existing instruction
+list, you can also use several strategies. The first one is to use a
+ListIterator over the instruction list:
+</p>
+
+<pre>
+ListIterator it = m.instructions.iterator();
+while (it.hasNext()) {
+ AbstractInsnNode n = (AbstractInsnNode) it.next();
+ if (...) {
+ it.add(new VarInsnNode(ALOAD, 0));
+ }
+}
+</pre>
+
+<p>
+It is also possible to convert instruction list into the array and iterate trough
+array elements:
+</p>
+
+<pre>
+AbstractInsnNode[] insns = m.instructions.toArray();
+for(int i = 0; i<insns.length; i++) {
+ AbstractInsnNode n = insns[i];
+ if (...) {
+ m.instructions.insert(n, new VarInsnNode(ALOAD, 0));
+ }
+}
+</pre>
+
+<p>
+If you want to insert these instructions through the MethodVisitor interface,
+you can use another instance of MethodNode as a MethodVisitor and then
+insert instructions collected by that instance into the instruction list.
+For example:
+</p>
+
+<pre>
+AbstractInsnNode[] insns = m.instructions.toArray();
+for(int i = 0; i<insns.length; i++) {
+ AbstractInsnNode n = insns[i];
+ if (...) {
+ MethodNode mn = new MethodNode();
+ mn.visitVarInsn(ALOAD, 0);
+ mn.visitVarInsn(ALOAD, 1);
+ m.instructions.insert(n, mn.instructions);
+ }
+}
+</pre>
+
+<p>
+ at since ASM 1.3.3
+</p>
+
+</body>
+</html>
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifiable.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifiable.java
new file mode 100644
index 0000000..1c94247
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifiable.java
@@ -0,0 +1,53 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import java.util.Map;
+
+/**
+ * An attribute that can print the ASM code to create an equivalent attribute.
+ *
+ * Implementation should print the ASM code that generates attribute data
+ * structures for current attribute state.
+ *
+ * @author Eugene Kuleshov
+ */
+public interface ASMifiable {
+
+ /**
+ * Prints the ASM code to create an attribute equal to this attribute.
+ *
+ * @param buf A buffer used for printing Java code.
+ * @param varName name of the variable in a printed code used to store
+ * attribute instance.
+ * @param labelNames map of label instances to their names.
+ */
+ void asmify(StringBuffer buf, String varName, Map labelNames);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAbstractVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAbstractVisitor.java
new file mode 100644
index 0000000..87256cd
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAbstractVisitor.java
@@ -0,0 +1,222 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.Map;
+
+/**
+ * An abstract ASMifier visitor.
+ *
+ * @author Eric Bruneton
+ */
+public class ASMifierAbstractVisitor extends AbstractVisitor {
+
+ /**
+ * The name of the variable for this visitor in the produced code.
+ */
+ protected String name;
+
+ /**
+ * The label names. This map associates String values to Label keys. It is
+ * used only in ASMifierMethodVisitor.
+ */
+ Map labelNames;
+
+ /**
+ * Constructs a new {@link ASMifierAbstractVisitor}.
+ *
+ * @param name the name of the variable for this visitor in the produced
+ * code.
+ */
+ protected ASMifierAbstractVisitor(final String name) {
+ this.name = name;
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param buf a string buffer.
+ * @param cst an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be <tt>null</tt>.
+ */
+ static void appendConstant(final StringBuffer buf, final Object cst) {
+ if (cst == null) {
+ buf.append("null");
+ } else if (cst instanceof String) {
+ appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append("Type.getType(\"");
+ buf.append(((Type) cst).getDescriptor());
+ buf.append("\")");
+ } else if (cst instanceof Byte) {
+ buf.append("new Byte((byte)").append(cst).append(')');
+ } else if (cst instanceof Boolean) {
+ buf.append(((Boolean) cst).booleanValue() ? "Boolean.TRUE" : "Boolean.FALSE");
+ } else if (cst instanceof Short) {
+ buf.append("new Short((short)").append(cst).append(')');
+ } else if (cst instanceof Character) {
+ int c = ((Character) cst).charValue();
+ buf.append("new Character((char)").append(c).append(')');
+ } else if (cst instanceof Integer) {
+ buf.append("new Integer(").append(cst).append(')');
+ } else if (cst instanceof Float) {
+ buf.append("new Float(\"").append(cst).append("\")");
+ } else if (cst instanceof Long) {
+ buf.append("new Long(").append(cst).append("L)");
+ } else if (cst instanceof Double) {
+ buf.append("new Double(\"").append(cst).append("\")");
+ } else if (cst instanceof byte[]) {
+ byte[] v = (byte[]) cst;
+ buf.append("new byte[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof boolean[]) {
+ boolean[] v = (boolean[]) cst;
+ buf.append("new boolean[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof short[]) {
+ short[] v = (short[]) cst;
+ buf.append("new short[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append("(short)").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof char[]) {
+ char[] v = (char[]) cst;
+ buf.append("new char[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",")
+ .append("(char)")
+ .append((int) v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof int[]) {
+ int[] v = (int[]) cst;
+ buf.append("new int[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]);
+ }
+ buf.append('}');
+ } else if (cst instanceof long[]) {
+ long[] v = (long[]) cst;
+ buf.append("new long[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('L');
+ }
+ buf.append('}');
+ } else if (cst instanceof float[]) {
+ float[] v = (float[]) cst;
+ buf.append("new float[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('f');
+ }
+ buf.append('}');
+ } else if (cst instanceof double[]) {
+ double[] v = (double[]) cst;
+ buf.append("new double[] {");
+ for (int i = 0; i < v.length; i++) {
+ buf.append(i == 0 ? "" : ",").append(v[i]).append('d');
+ }
+ buf.append('}');
+ }
+ }
+
+ /**
+ * Prints the ASM code that generates the given annotation.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append("{\n")
+ .append("av0 = ")
+ .append(name)
+ .append(".visitAnnotation(");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ /**
+ * Prints the ASM code that generates the given attribute.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append("// ATTRIBUTE ").append(attr.type).append('\n');
+ if (attr instanceof ASMifiable) {
+ buf.append("{\n");
+ ((ASMifiable) attr).asmify(buf, "attr", labelNames);
+ buf.append(name).append(".visitAttribute(attr);\n");
+ buf.append("}\n");
+ }
+ text.add(buf.toString());
+ }
+
+ /**
+ * Prints the ASM code to end the visit.
+ */
+ public void visitEnd() {
+ buf.setLength(0);
+ buf.append(name).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+
+ /**
+ * Appends a string representation of the given constant to the given
+ * buffer.
+ *
+ * @param cst an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double} or {@link String} object. May be <tt>null</tt>.
+ */
+ void appendConstant(final Object cst) {
+ appendConstant(buf, cst);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAnnotationVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAnnotationVisitor.java
new file mode 100644
index 0000000..dc1802d
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierAnnotationVisitor.java
@@ -0,0 +1,127 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+
+/**
+ * An {@link AnnotationVisitor} that prints the ASM code that generates the
+ * annotations it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class ASMifierAnnotationVisitor extends AbstractVisitor implements
+ AnnotationVisitor
+{
+
+ /**
+ * Identifier of the annotation visitor variable in the produced code.
+ */
+ protected final int id;
+
+ /**
+ * Constructs a new {@link ASMifierAnnotationVisitor}.
+ *
+ * @param id identifier of the annotation visitor variable in the produced
+ * code.
+ */
+ public ASMifierAnnotationVisitor(final int id) {
+ this.id = id;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visit(");
+ ASMifierAbstractVisitor.appendConstant(buf, name);
+ buf.append(", ");
+ ASMifierAbstractVisitor.appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnum(");
+ ASMifierAbstractVisitor.appendConstant(buf, name);
+ buf.append(", ");
+ ASMifierAbstractVisitor.appendConstant(buf, desc);
+ buf.append(", ");
+ ASMifierAbstractVisitor.appendConstant(buf, value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitAnnotation(");
+ ASMifierAbstractVisitor.appendConstant(buf, name);
+ buf.append(", ");
+ ASMifierAbstractVisitor.appendConstant(buf, desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("AnnotationVisitor av").append(id + 1).append(" = av");
+ buf.append(id).append(".visitArray(");
+ ASMifierAbstractVisitor.appendConstant(buf, name);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(id + 1);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ public void visitEnd() {
+ buf.setLength(0);
+ buf.append("av").append(id).append(".visitEnd();\n");
+ text.add(buf.toString());
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierClassVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierClassVisitor.java
new file mode 100644
index 0000000..d5921d2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierClassVisitor.java
@@ -0,0 +1,575 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+
+/**
+ * A {@link ClassVisitor} that prints the ASM code that generates the classes it
+ * visits. This class visitor can be used to quickly write ASM code to generate
+ * some given bytecode: <ul> <li>write the Java source code equivalent to the
+ * bytecode you want to generate;</li> <li>compile it with <tt>javac</tt>;</li>
+ * <li>make a {@link ASMifierClassVisitor} visit this compiled class (see the
+ * {@link #main main} method);</li> <li>edit the generated source code, if
+ * necessary.</li> </ul> The source code printed when visiting the
+ * <tt>Hello</tt> class is the following: <p> <blockquote>
+ *
+ * <pre>
+ * import org.powermock.api.mockito.repackaged.asm.*;
+ *
+ * public class HelloDump implements Opcodes {
+ *
+ * public static byte[] dump() throws Exception {
+ *
+ * ClassWriter cw = new ClassWriter(0);
+ * FieldVisitor fv;
+ * MethodVisitor mv;
+ * AnnotationVisitor av0;
+ *
+ * cw.visit(49,
+ * ACC_PUBLIC + ACC_SUPER,
+ * "Hello",
+ * null,
+ * "java/lang/Object",
+ * null);
+ *
+ * cw.visitSource("Hello.java", null);
+ *
+ * {
+ * mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
+ * mv.visitVarInsn(ALOAD, 0);
+ * mv.visitMethodInsn(INVOKESPECIAL,
+ * "java/lang/Object",
+ * "<init>",
+ * "()V");
+ * mv.visitInsn(RETURN);
+ * mv.visitMaxs(1, 1);
+ * mv.visitEnd();
+ * }
+ * {
+ * mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC,
+ * "main",
+ * "([Ljava/lang/String;)V",
+ * null,
+ * null);
+ * mv.visitFieldInsn(GETSTATIC,
+ * "java/lang/System",
+ * "out",
+ * "Ljava/io/PrintStream;");
+ * mv.visitLdcInsn("hello");
+ * mv.visitMethodInsn(INVOKEVIRTUAL,
+ * "java/io/PrintStream",
+ * "println",
+ * "(Ljava/lang/String;)V");
+ * mv.visitInsn(RETURN);
+ * mv.visitMaxs(2, 1);
+ * mv.visitEnd();
+ * }
+ * cw.visitEnd();
+ *
+ * return cw.toByteArray();
+ * }
+ * }
+ *
+ * </pre>
+ *
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ *
+ * <pre>
+ * public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ASMifierClassVisitor extends ASMifierAbstractVisitor implements
+ ClassVisitor
+{
+
+ /**
+ * Pseudo access flag used to distinguish class access flags.
+ */
+ private static final int ACCESS_CLASS = 262144;
+
+ /**
+ * Pseudo access flag used to distinguish field access flags.
+ */
+ private static final int ACCESS_FIELD = 524288;
+
+ /**
+ * Pseudo access flag used to distinguish inner class flags.
+ */
+ private static final int ACCESS_INNER = 1048576;
+
+ /**
+ * The print writer to be used to print the class.
+ */
+ protected final PrintWriter pw;
+
+ /**
+ * Constructs a new {@link ASMifierClassVisitor} object.
+ *
+ * @param pw the print writer to be used to print the class.
+ */
+ public ASMifierClassVisitor(final PrintWriter pw) {
+ super("cw");
+ this.pw = pw;
+ }
+
+ /**
+ * Prints the ASM source code to generate the given class to the standard
+ * output. <p> Usage: ASMifierClassVisitor [-debug] <fully qualified
+ * class name or class file name>
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Prints the ASM code to generate the given class.");
+ System.err.println("Usage: ASMifierClassVisitor [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1)
+ {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new ASMifierClassVisitor(new PrintWriter(System.out)),
+ getDefaultAttributes(),
+ flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ String simpleName;
+ int n = name.lastIndexOf('/');
+ if (n == -1) {
+ simpleName = name;
+ } else {
+ text.add("package asm." + name.substring(0, n).replace('/', '.')
+ + ";\n");
+ simpleName = name.substring(n + 1);
+ }
+ text.add("import java.util.*;\n");
+ text.add("import org.powermock.api.mockito.repackaged.asm.*;\n");
+ text.add("import org.powermock.api.mockito.repackaged.asm.attrs.*;\n");
+ text.add("public class " + simpleName + "Dump implements Opcodes {\n\n");
+ text.add("public static byte[] dump () throws Exception {\n\n");
+ text.add("ClassWriter cw = new ClassWriter(0);\n");
+ text.add("FieldVisitor fv;\n");
+ text.add("MethodVisitor mv;\n");
+ text.add("AnnotationVisitor av0;\n\n");
+
+ buf.setLength(0);
+ buf.append("cw.visit(");
+ switch (version) {
+ case Opcodes.V1_1:
+ buf.append("V1_1");
+ break;
+ case Opcodes.V1_2:
+ buf.append("V1_2");
+ break;
+ case Opcodes.V1_3:
+ buf.append("V1_3");
+ break;
+ case Opcodes.V1_4:
+ buf.append("V1_4");
+ break;
+ case Opcodes.V1_5:
+ buf.append("V1_5");
+ break;
+ case Opcodes.V1_6:
+ buf.append("V1_6");
+ break;
+ default:
+ buf.append(version);
+ break;
+ }
+ buf.append(", ");
+ appendAccess(access | ACCESS_CLASS);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(superName);
+ buf.append(", ");
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < interfaces.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(interfaces[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ buf.append("cw.visitSource(");
+ appendConstant(file);
+ buf.append(", ");
+ appendConstant(debug);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("cw.visitOuterClass(");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ buf.setLength(0);
+ buf.append("cw.visitInnerClass(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(outerName);
+ buf.append(", ");
+ appendConstant(innerName);
+ buf.append(", ");
+ appendAccess(access | ACCESS_INNER);
+ buf.append(");\n\n");
+ text.add(buf.toString());
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("fv = cw.visitField(");
+ appendAccess(access | ACCESS_FIELD);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendConstant(value);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifierFieldVisitor aav = new ASMifierFieldVisitor();
+ text.add(aav.getText());
+ text.add("}\n");
+ return aav;
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("mv = cw.visitMethod(");
+ appendAccess(access);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append("new String[] {");
+ for (int i = 0; i < exceptions.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendConstant(exceptions[i]);
+ }
+ buf.append(" }");
+ } else {
+ buf.append("null");
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifierMethodVisitor acv = createASMifierMethodVisitor();
+ text.add(acv.getText());
+ text.add("}\n");
+ return acv;
+ }
+
+ protected ASMifierMethodVisitor createASMifierMethodVisitor() {
+ return new ASMifierMethodVisitor();
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append("{\n");
+ buf.append("av0 = cw.visitAnnotation(");
+ appendConstant(desc);
+ buf.append(", ");
+ buf.append(visible);
+ buf.append(");\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ public void visitEnd() {
+ text.add("cw.visitEnd();\n\n");
+ text.add("return cw.toByteArray();\n");
+ text.add("}\n");
+ text.add("}\n");
+ printList(pw, text);
+ pw.flush();
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Appends a string representation of the given access modifiers to {@link
+ * #buf buf}.
+ *
+ * @param access some access modifiers.
+ */
+ void appendAccess(final int access) {
+ boolean first = true;
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("ACC_PUBLIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("ACC_PRIVATE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("ACC_PROTECTED");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_FINAL");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STATIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ if ((access & ACCESS_CLASS) == 0) {
+ buf.append("ACC_SYNCHRONIZED");
+ } else {
+ buf.append("ACC_SUPER");
+ }
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0
+ && (access & ACCESS_FIELD) != 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VOLATILE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_BRIDGE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_VARARGS");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0
+ && (access & ACCESS_FIELD) != 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_TRANSIENT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_NATIVE) != 0 && (access & ACCESS_CLASS) == 0
+ && (access & ACCESS_FIELD) == 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_NATIVE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0
+ && ((access & ACCESS_CLASS) != 0
+ || (access & ACCESS_FIELD) != 0 || (access & ACCESS_INNER) != 0))
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ENUM");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ANNOTATION) != 0
+ && (access & ACCESS_CLASS) != 0)
+ {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ANNOTATION");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_ABSTRACT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_INTERFACE");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_STRICT");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_SYNTHETIC");
+ first = false;
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ if (!first) {
+ buf.append(" + ");
+ }
+ buf.append("ACC_DEPRECATED");
+ first = false;
+ }
+ if (first) {
+ buf.append('0');
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierFieldVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierFieldVisitor.java
new file mode 100644
index 0000000..65a83b3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierFieldVisitor.java
@@ -0,0 +1,50 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that prints the ASM code that generates the fields it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class ASMifierFieldVisitor extends ASMifierAbstractVisitor implements
+ FieldVisitor
+{
+
+ /**
+ * Constructs a new {@link ASMifierFieldVisitor}.
+ */
+ public ASMifierFieldVisitor() {
+ super("fv");
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierMethodVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierMethodVisitor.java
new file mode 100644
index 0000000..75d5c01
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/ASMifierMethodVisitor.java
@@ -0,0 +1,443 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+
+import java.util.HashMap;
+
+/**
+ * A {@link MethodVisitor} that prints the ASM code that generates the methods
+ * it visits.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ASMifierMethodVisitor extends ASMifierAbstractVisitor implements
+ MethodVisitor
+{
+
+ /**
+ * Constructs a new {@link ASMifierMethodVisitor} object.
+ */
+ public ASMifierMethodVisitor() {
+ super("mv");
+ this.labelNames = new HashMap();
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ buf.setLength(0);
+ buf.append("{\n").append("av0 = mv.visitAnnotationDefault();\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append("{\n")
+ .append("av0 = mv.visitParameterAnnotation(")
+ .append(parameter)
+ .append(", ");
+ appendConstant(desc);
+ buf.append(", ").append(visible).append(");\n");
+ text.add(buf.toString());
+ ASMifierAnnotationVisitor av = new ASMifierAnnotationVisitor(0);
+ text.add(av.getText());
+ text.add("}\n");
+ return av;
+ }
+
+ public void visitCode() {
+ text.add("mv.visitCode();\n");
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ buf.setLength(0);
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ declareFrameTypes(nLocal, local);
+ declareFrameTypes(nStack, stack);
+ if (type == Opcodes.F_NEW) {
+ buf.append("mv.visitFrame(Opcodes.F_NEW, ");
+ } else {
+ buf.append("mv.visitFrame(Opcodes.F_FULL, ");
+ }
+ buf.append(nLocal).append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, ").append(nStack).append(", new Object[] {");
+ appendFrameTypes(nStack, stack);
+ buf.append('}');
+ break;
+ case Opcodes.F_APPEND:
+ declareFrameTypes(nLocal, local);
+ buf.append("mv.visitFrame(Opcodes.F_APPEND,")
+ .append(nLocal)
+ .append(", new Object[] {");
+ appendFrameTypes(nLocal, local);
+ buf.append("}, 0, null");
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("mv.visitFrame(Opcodes.F_CHOP,")
+ .append(nLocal)
+ .append(", null, 0, null");
+ break;
+ case Opcodes.F_SAME:
+ buf.append("mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null");
+ break;
+ case Opcodes.F_SAME1:
+ declareFrameTypes(1, stack);
+ buf.append("mv.visitFrame(Opcodes.F_SAME1, 0, null, 1, new Object[] {");
+ appendFrameTypes(1, stack);
+ buf.append('}');
+ break;
+ }
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append("mv.visitInsn(").append(OPCODES[opcode]).append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append("mv.visitIntInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(opcode == Opcodes.NEWARRAY
+ ? TYPES[operand]
+ : Integer.toString(operand))
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append("mv.visitVarInsn(")
+ .append(OPCODES[opcode])
+ .append(", ")
+ .append(var)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append("mv.visitTypeInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("mv.visitFieldInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append("mv.visitMethodInsn(").append(OPCODES[opcode]).append(", ");
+ appendConstant(owner);
+ buf.append(", ");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append("mv.visitJumpInsn(").append(OPCODES[opcode]).append(", ");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ declareLabel(label);
+ buf.append("mv.visitLabel(");
+ appendLabel(label);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append("mv.visitLdcInsn(");
+ appendConstant(cst);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append("mv.visitIincInsn(")
+ .append(var)
+ .append(", ")
+ .append(increment)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append("mv.visitTableSwitchInsn(")
+ .append(min)
+ .append(", ")
+ .append(max)
+ .append(", ");
+ appendLabel(dflt);
+ buf.append(", new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ for (int i = 0; i < labels.length; ++i) {
+ declareLabel(labels[i]);
+ }
+ declareLabel(dflt);
+
+ buf.append("mv.visitLookupSwitchInsn(");
+ appendLabel(dflt);
+ buf.append(", new int[] {");
+ for (int i = 0; i < keys.length; ++i) {
+ buf.append(i == 0 ? " " : ", ").append(keys[i]);
+ }
+ buf.append(" }, new Label[] {");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(i == 0 ? " " : ", ");
+ appendLabel(labels[i]);
+ }
+ buf.append(" });\n");
+ text.add(buf.toString());
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append("mv.visitMultiANewArrayInsn(");
+ appendConstant(desc);
+ buf.append(", ").append(dims).append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ buf.setLength(0);
+ declareLabel(start);
+ declareLabel(end);
+ declareLabel(handler);
+ buf.append("mv.visitTryCatchBlock(");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ");
+ appendLabel(handler);
+ buf.append(", ");
+ appendConstant(type);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ buf.setLength(0);
+ buf.append("mv.visitLocalVariable(");
+ appendConstant(name);
+ buf.append(", ");
+ appendConstant(desc);
+ buf.append(", ");
+ appendConstant(signature);
+ buf.append(", ");
+ appendLabel(start);
+ buf.append(", ");
+ appendLabel(end);
+ buf.append(", ").append(index).append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append("mv.visitLineNumber(").append(line).append(", ");
+ appendLabel(start);
+ buf.append(");\n");
+ text.add(buf.toString());
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append("mv.visitMaxs(")
+ .append(maxStack)
+ .append(", ")
+ .append(maxLocals)
+ .append(");\n");
+ text.add(buf.toString());
+ }
+
+ private void declareFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (o[i] instanceof Label) {
+ declareLabel((Label) o[i]);
+ }
+ }
+ }
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(", ");
+ }
+ if (o[i] instanceof String) {
+ appendConstant(o[i]);
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ buf.append("Opcodes.TOP");
+ break;
+ case 1:
+ buf.append("Opcodes.INTEGER");
+ break;
+ case 2:
+ buf.append("Opcodes.FLOAT");
+ break;
+ case 3:
+ buf.append("Opcodes.DOUBLE");
+ break;
+ case 4:
+ buf.append("Opcodes.LONG");
+ break;
+ case 5:
+ buf.append("Opcodes.NULL");
+ break;
+ case 6:
+ buf.append("Opcodes.UNINITIALIZED_THIS");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends a declaration of the given label to {@link #buf buf}. This
+ * declaration is of the form "Label lXXX = new Label();". Does nothing if
+ * the given label has already been declared.
+ *
+ * @param l a label.
+ */
+ private void declareLabel(final Label l) {
+ String name = (String) labelNames.get(l);
+ if (name == null) {
+ name = "l" + labelNames.size();
+ labelNames.put(l, name);
+ buf.append("Label ").append(name).append(" = new Label();\n");
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. The given label
+ * <i>must</i> already have a name. One way to ensure this is to always
+ * call {@link #declareLabel declared} before calling this method.
+ *
+ * @param l a label.
+ */
+ private void appendLabel(final Label l) {
+ buf.append((String) labelNames.get(l));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/AbstractVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/AbstractVisitor.java
new file mode 100644
index 0000000..03291f5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/AbstractVisitor.java
@@ -0,0 +1,202 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * An abstract visitor.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class AbstractVisitor {
+
+ /**
+ * The names of the Java Virtual Machine opcodes.
+ */
+ public static final String[] OPCODES;
+ /**
+ * Types for <code>operand</code> parameter of the
+ * {@link org.powermock.api.mockito.repackaged.asm.MethodVisitor#visitIntInsn} method when
+ * <code>opcode</code> is <code>NEWARRAY</code>.
+ */
+ public static final String[] TYPES;
+
+ static {
+ String s = "NOP,ACONST_NULL,ICONST_M1,ICONST_0,ICONST_1,ICONST_2,"
+ + "ICONST_3,ICONST_4,ICONST_5,LCONST_0,LCONST_1,FCONST_0,"
+ + "FCONST_1,FCONST_2,DCONST_0,DCONST_1,BIPUSH,SIPUSH,LDC,,,"
+ + "ILOAD,LLOAD,FLOAD,DLOAD,ALOAD,,,,,,,,,,,,,,,,,,,,,IALOAD,"
+ + "LALOAD,FALOAD,DALOAD,AALOAD,BALOAD,CALOAD,SALOAD,ISTORE,"
+ + "LSTORE,FSTORE,DSTORE,ASTORE,,,,,,,,,,,,,,,,,,,,,IASTORE,"
+ + "LASTORE,FASTORE,DASTORE,AASTORE,BASTORE,CASTORE,SASTORE,POP,"
+ + "POP2,DUP,DUP_X1,DUP_X2,DUP2,DUP2_X1,DUP2_X2,SWAP,IADD,LADD,"
+ + "FADD,DADD,ISUB,LSUB,FSUB,DSUB,IMUL,LMUL,FMUL,DMUL,IDIV,LDIV,"
+ + "FDIV,DDIV,IREM,LREM,FREM,DREM,INEG,LNEG,FNEG,DNEG,ISHL,LSHL,"
+ + "ISHR,LSHR,IUSHR,LUSHR,IAND,LAND,IOR,LOR,IXOR,LXOR,IINC,I2L,"
+ + "I2F,I2D,L2I,L2F,L2D,F2I,F2L,F2D,D2I,D2L,D2F,I2B,I2C,I2S,LCMP,"
+ + "FCMPL,FCMPG,DCMPL,DCMPG,IFEQ,IFNE,IFLT,IFGE,IFGT,IFLE,"
+ + "IF_ICMPEQ,IF_ICMPNE,IF_ICMPLT,IF_ICMPGE,IF_ICMPGT,IF_ICMPLE,"
+ + "IF_ACMPEQ,IF_ACMPNE,GOTO,JSR,RET,TABLESWITCH,LOOKUPSWITCH,"
+ + "IRETURN,LRETURN,FRETURN,DRETURN,ARETURN,RETURN,GETSTATIC,"
+ + "PUTSTATIC,GETFIELD,PUTFIELD,INVOKEVIRTUAL,INVOKESPECIAL,"
+ + "INVOKESTATIC,INVOKEINTERFACE,,NEW,NEWARRAY,ANEWARRAY,"
+ + "ARRAYLENGTH,ATHROW,CHECKCAST,INSTANCEOF,MONITORENTER,"
+ + "MONITOREXIT,,MULTIANEWARRAY,IFNULL,IFNONNULL,";
+ OPCODES = new String[200];
+ int i = 0;
+ int j = 0;
+ int l;
+ while ((l = s.indexOf(',', j)) > 0) {
+ OPCODES[i++] = j + 1 == l ? null : s.substring(j, l);
+ j = l + 1;
+ }
+
+ s = "T_BOOLEAN,T_CHAR,T_FLOAT,T_DOUBLE,T_BYTE,T_SHORT,T_INT,T_LONG,";
+ TYPES = new String[12];
+ j = 0;
+ i = 4;
+ while ((l = s.indexOf(',', j)) > 0) {
+ TYPES[i++] = s.substring(j, l);
+ j = l + 1;
+ }
+ }
+
+ /**
+ * The text to be printed. Since the code of methods is not necessarily
+ * visited in sequential order, one method after the other, but can be
+ * interlaced (some instructions from method one, then some instructions
+ * from method two, then some instructions from method one again...), it is
+ * not possible to print the visited instructions directly to a sequential
+ * stream. A class is therefore printed in a two steps process: a string
+ * tree is constructed during the visit, and printed to a sequential stream
+ * at the end of the visit. This string tree is stored in this field, as a
+ * string list that can contain other string lists, which can themselves
+ * contain other string lists, and so on.
+ */
+ public final List text;
+
+ /**
+ * A buffer that can be used to create strings.
+ */
+ protected final StringBuffer buf;
+
+ /**
+ * Constructs a new {@link AbstractVisitor}.
+ */
+ protected AbstractVisitor() {
+ this.text = new ArrayList();
+ this.buf = new StringBuffer();
+ }
+
+ /**
+ * Appends a quoted string to a given buffer.
+ *
+ * @param buf the buffer where the string must be added.
+ * @param s the string to be added.
+ */
+ public static void appendString(final StringBuffer buf, final String s) {
+ buf.append('\"');
+ for (int i = 0; i < s.length(); ++i) {
+ char c = s.charAt(i);
+ if (c == '\n') {
+ buf.append("\\n");
+ } else if (c == '\r') {
+ buf.append("\\r");
+ } else if (c == '\\') {
+ buf.append("\\\\");
+ } else if (c == '"') {
+ buf.append("\\\"");
+ } else if (c < 0x20 || c > 0x7f) {
+ buf.append("\\u");
+ if (c < 0x10) {
+ buf.append("000");
+ } else if (c < 0x100) {
+ buf.append("00");
+ } else if (c < 0x1000) {
+ buf.append('0');
+ }
+ buf.append(Integer.toString(c, 16));
+ } else {
+ buf.append(c);
+ }
+ }
+ buf.append('\"');
+ }
+
+ /**
+ * Prints the given string tree.
+ *
+ * @param pw the writer to be used to print the tree.
+ * @param l a string tree, i.e., a string list that can contain other string
+ * lists, and so on recursively.
+ */
+ static void printList(final PrintWriter pw, final List l) {
+ for (int i = 0; i < l.size(); ++i) {
+ Object o = l.get(i);
+ if (o instanceof List) {
+ printList(pw, (List) o);
+ } else {
+ pw.print(o.toString());
+ }
+ }
+ }
+
+ /**
+ * Returns the default {@link ASMifiable} prototypes.
+ *
+ * @return the default {@link ASMifiable} prototypes.
+ */
+ public static Attribute[] getDefaultAttributes() {
+ return new Attribute[0];
+ }
+
+ /**
+ * Returns the text constructed by this visitor.
+ *
+ * @return the text constructed by this visitor.
+ */
+ public List getText() {
+ return text;
+ }
+
+ /**
+ * Prints the text constructed by this visitor.
+ *
+ * @param pw the print writer to be used.
+ */
+ public void print(final PrintWriter pw) {
+ printList(pw, text);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckAnnotationAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckAnnotationAdapter.java
new file mode 100644
index 0000000..b6a14be
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckAnnotationAdapter.java
@@ -0,0 +1,132 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckAnnotationAdapter implements AnnotationVisitor {
+
+ private final AnnotationVisitor av;
+
+ private final boolean named;
+
+ private boolean end;
+
+ public CheckAnnotationAdapter(final AnnotationVisitor av) {
+ this(av, true);
+ }
+
+ CheckAnnotationAdapter(final AnnotationVisitor av, final boolean named) {
+ this.av = av;
+ this.named = named;
+ }
+
+ public void visit(final String name, final Object value) {
+ checkEnd();
+ checkName(name);
+ if (!(value instanceof Byte || value instanceof Boolean
+ || value instanceof Character || value instanceof Short
+ || value instanceof Integer || value instanceof Long
+ || value instanceof Float || value instanceof Double
+ || value instanceof String || value instanceof Type
+ || value instanceof byte[] || value instanceof boolean[]
+ || value instanceof char[] || value instanceof short[]
+ || value instanceof int[] || value instanceof long[]
+ || value instanceof float[] || value instanceof double[]))
+ {
+ throw new IllegalArgumentException("Invalid annotation value");
+ }
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (value == null) {
+ throw new IllegalArgumentException("Invalid enum value");
+ }
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ checkEnd();
+ checkName(name);
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(av == null
+ ? null
+ : av.visitAnnotation(name, desc));
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ checkEnd();
+ checkName(name);
+ return new CheckAnnotationAdapter(av == null
+ ? null
+ : av.visitArray(name), false);
+ }
+
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+
+ private void checkName(final String name) {
+ if (named && name == null) {
+ throw new IllegalArgumentException("Annotation value name must not be null");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckClassAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckClassAdapter.java
new file mode 100644
index 0000000..4a0e3e3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckClassAdapter.java
@@ -0,0 +1,480 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassAdapter;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.tree.ClassNode;
+import org.powermock.api.mockito.repackaged.asm.tree.MethodNode;
+import org.powermock.api.mockito.repackaged.asm.tree.TryCatchBlockNode;
+import org.powermock.api.mockito.repackaged.asm.tree.analysis.Analyzer;
+import org.powermock.api.mockito.repackaged.asm.tree.analysis.Frame;
+import org.powermock.api.mockito.repackaged.asm.tree.analysis.SimpleVerifier;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * A {@link ClassAdapter} that checks that its methods are properly used. More
+ * precisely this class adapter checks each method call individually, based
+ * <i>only</i> on its arguments, but does <i>not</i> check the <i>sequence</i>
+ * of method calls. For example, the invalid sequence
+ * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
+ * "i", "D", null)</tt>
+ * will <i>not</i> be detected by this class adapter.
+ *
+ * <p><code>CheckClassAdapter</code> can be also used to verify bytecode
+ * transformations in order to make sure transformed bytecode is sane. For
+ * example:
+ *
+ * <pre>
+ * InputStream is = ...; // get bytes for the source class
+ * ClassReader cr = new ClassReader(is);
+ * ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS);
+ * ClassVisitor cv = new <b>MyClassAdapter</b>(new CheckClassAdapter(cw));
+ * cr.accept(cv, 0);
+ *
+ * StringWriter sw = new StringWriter();
+ * PrintWriter pw = new PrintWriter(sw);
+ * CheckClassAdapter.verify(new ClassReader(cw.toByteArray()), false, pw);
+ * assertTrue(sw.toString(), sw.toString().length()==0);
+ * </pre>
+ *
+ * Above code runs transformed bytecode trough the
+ * <code>CheckClassAdapter</code>. It won't be exactly the same verification
+ * as JVM does, but it run data flow analysis for the code of each method and
+ * checks that expectations are met for each method instruction.
+ *
+ * <p>If method bytecode has errors, assertion text will show the erroneous
+ * instruction number and dump of the failed method with information about
+ * locals and stack slot for each instruction. For example (format is -
+ * insnNumber locals : stack):
+ *
+ * <pre>
+ * org.powermock.api.mockito.repackaged.asm.tree.analysis.AnalyzerException: Error at instruction 71: Expected I, but found .
+ * at org.powermock.api.mockito.repackaged.asm.tree.analysis.Analyzer.analyze(Analyzer.java:289)
+ * at org.powermock.api.mockito.repackaged.asm.util.CheckClassAdapter.verify(CheckClassAdapter.java:135)
+ * ...
+ * remove()V
+ * 00000 LinkedBlockingQueue$Itr . . . . . . . . :
+ * ICONST_0
+ * 00001 LinkedBlockingQueue$Itr . . . . . . . . : I
+ * ISTORE 2
+ * 00001 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
+ * ...
+ *
+ * 00071 LinkedBlockingQueue$Itr <b>.</b> I . . . . . . :
+ * ILOAD 1
+ * 00072 <b>?</b>
+ * INVOKESPECIAL java/lang/Integer.<init> (I)V
+ * ...
+ * </pre>
+ *
+ * In the above output you can see that variable 1 loaded by
+ * <code>ILOAD 1</code> instruction at position <code>00071</code> is not
+ * initialized. You can also see that at the beginning of the method (code
+ * inserted by the transformation) variable 2 is initialized.
+ *
+ * <p>Note that when used like that, <code>CheckClassAdapter.verify()</code>
+ * can trigger additional class loading, because it is using
+ * <code>SimpleVerifier</code>.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckClassAdapter extends ClassAdapter {
+
+ /**
+ * <tt>true</tt> if the visit method has been called.
+ */
+ private boolean start;
+
+ /**
+ * <tt>true</tt> if the visitSource method has been called.
+ */
+ private boolean source;
+
+ /**
+ * <tt>true</tt> if the visitOuterClass method has been called.
+ */
+ private boolean outer;
+
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean end;
+
+ /**
+ * Constructs a new {@link CheckClassAdapter}.
+ *
+ * @param cv the class visitor to which this adapter must delegate calls.
+ */
+ public CheckClassAdapter(final ClassVisitor cv) {
+ super(cv);
+ }
+
+ /**
+ * Checks a given class. <p> Usage: CheckClassAdapter <fully qualified
+ * class name or class file name>
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ if (args.length != 1) {
+ System.err.println("Verifies the given class.");
+ System.err.println("Usage: CheckClassAdapter "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[0].endsWith(".class")) {
+ cr = new ClassReader(new FileInputStream(args[0]));
+ } else {
+ cr = new ClassReader(args[0]);
+ }
+
+ verify(cr, false, new PrintWriter(System.err));
+ }
+
+ /**
+ * Checks a given class
+ *
+ * @param cr a <code>ClassReader</code> that contains bytecode for the
+ * analysis.
+ * @param dump true if bytecode should be printed out not only when errors
+ * are found.
+ * @param pw write where results going to be printed
+ */
+ public static void verify(
+ final ClassReader cr,
+ final boolean dump,
+ final PrintWriter pw)
+ {
+ ClassNode cn = new ClassNode();
+ cr.accept(new CheckClassAdapter(cn), ClassReader.SKIP_DEBUG);
+
+ Type syperType = cn.superName == null
+ ? null
+ : Type.getObjectType(cn.superName);
+ List methods = cn.methods;
+ for (int i = 0; i < methods.size(); ++i) {
+ MethodNode method = (MethodNode) methods.get(i);
+ Analyzer a = new Analyzer(new SimpleVerifier(Type.getObjectType(cn.name),
+ syperType,
+ false));
+ try {
+ a.analyze(cn.name, method);
+ if (!dump) {
+ continue;
+ }
+ } catch (Exception e) {
+ e.printStackTrace(pw);
+ }
+ Frame[] frames = a.getFrames();
+
+ TraceMethodVisitor mv = new TraceMethodVisitor();
+
+ pw.println(method.name + method.desc);
+ for (int j = 0; j < method.instructions.size(); ++j) {
+ method.instructions.get(j).accept(mv);
+
+ StringBuffer s = new StringBuffer();
+ Frame f = frames[j];
+ if (f == null) {
+ s.append('?');
+ } else {
+ for (int k = 0; k < f.getLocals(); ++k) {
+ s.append(getShortName(f.getLocal(k).toString()))
+ .append(' ');
+ }
+ s.append(" : ");
+ for (int k = 0; k < f.getStackSize(); ++k) {
+ s.append(getShortName(f.getStack(k).toString()))
+ .append(' ');
+ }
+ }
+ while (s.length() < method.maxStack + method.maxLocals + 1) {
+ s.append(' ');
+ }
+ pw.print(Integer.toString(j + 100000).substring(1));
+ pw.print(" " + s + " : " + mv.buf); // mv.text.get(j));
+ }
+ for (int j = 0; j < method.tryCatchBlocks.size(); ++j) {
+ ((TryCatchBlockNode) method.tryCatchBlocks.get(j)).accept(mv);
+ pw.print(" " + mv.buf);
+ }
+ pw.println();
+ }
+ pw.flush();
+ }
+
+ private static String getShortName(final String name) {
+ int n = name.lastIndexOf('/');
+ int k = name.length();
+ if (name.charAt(k - 1) == ';') {
+ k--;
+ }
+ return n == -1 ? name : name.substring(n + 1, k);
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ /**
+ * Checks that the given access flags do not contain invalid flags. This
+ * method also checks that mutually incompatible flags are not set
+ * simultaneously.
+ *
+ * @param access the access flags to be checked
+ * @param possibleAccess the valid access flags.
+ */
+ static void checkAccess(final int access, final int possibleAccess) {
+ if ((access & ~possibleAccess) != 0) {
+ throw new IllegalArgumentException("Invalid access flags: "
+ + access);
+ }
+ int pub = (access & Opcodes.ACC_PUBLIC) == 0 ? 0 : 1;
+ int pri = (access & Opcodes.ACC_PRIVATE) == 0 ? 0 : 1;
+ int pro = (access & Opcodes.ACC_PROTECTED) == 0 ? 0 : 1;
+ if (pub + pri + pro > 1) {
+ throw new IllegalArgumentException("public private and protected are mutually exclusive: "
+ + access);
+ }
+ int fin = (access & Opcodes.ACC_FINAL) == 0 ? 0 : 1;
+ int abs = (access & Opcodes.ACC_ABSTRACT) == 0 ? 0 : 1;
+ if (fin + abs > 1) {
+ throw new IllegalArgumentException("final and abstract are mutually exclusive: "
+ + access);
+ }
+ }
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ if (start) {
+ throw new IllegalStateException("visit must be called only once");
+ }
+ start = true;
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_FINAL
+ + Opcodes.ACC_SUPER + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM
+ + Opcodes.ACC_DEPRECATED);
+ if (name == null || !name.endsWith("package-info")) {
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ }
+ if ("java/lang/Object".equals(name)) {
+ if (superName != null) {
+ throw new IllegalArgumentException("The super class name of the Object class must be 'null'");
+ }
+ } else {
+ CheckMethodAdapter.checkInternalName(superName, "super class name");
+ }
+ if (signature != null) {
+ CheckMethodAdapter.checkClassSignature(signature);
+ }
+ if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ if (!"java/lang/Object".equals(superName)) {
+ throw new IllegalArgumentException("The super class name of interfaces must be 'java/lang/Object'");
+ }
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; ++i) {
+ CheckMethodAdapter.checkInternalName(interfaces[i],
+ "interface name at index " + i);
+ }
+ }
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ public void visitSource(final String file, final String debug) {
+ checkState();
+ if (source) {
+ throw new IllegalStateException("visitSource can be called only once.");
+ }
+ source = true;
+ cv.visitSource(file, debug);
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkState();
+ if (outer) {
+ throw new IllegalStateException("visitOuterClass can be called only once.");
+ }
+ outer = true;
+ if (owner == null) {
+ throw new IllegalArgumentException("Illegal outer class owner");
+ }
+ if (desc != null) {
+ CheckMethodAdapter.checkMethodDesc(desc);
+ }
+ cv.visitOuterClass(owner, name, desc);
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ checkState();
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ if (outerName != null) {
+ CheckMethodAdapter.checkInternalName(outerName, "outer class name");
+ }
+ if (innerName != null) {
+ CheckMethodAdapter.checkIdentifier(innerName, "inner class name");
+ }
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_INTERFACE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ANNOTATION + Opcodes.ACC_ENUM);
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_VOLATILE
+ + Opcodes.ACC_TRANSIENT + Opcodes.ACC_SYNTHETIC
+ + Opcodes.ACC_ENUM + Opcodes.ACC_DEPRECATED);
+ CheckMethodAdapter.checkIdentifier(name, "field name");
+ CheckMethodAdapter.checkDesc(desc, false);
+ if (signature != null) {
+ CheckMethodAdapter.checkFieldSignature(signature);
+ }
+ if (value != null) {
+ CheckMethodAdapter.checkConstant(value);
+ }
+ FieldVisitor av = cv.visitField(access, name, desc, signature, value);
+ return new CheckFieldAdapter(av);
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ checkState();
+ checkAccess(access, Opcodes.ACC_PUBLIC + Opcodes.ACC_PRIVATE
+ + Opcodes.ACC_PROTECTED + Opcodes.ACC_STATIC
+ + Opcodes.ACC_FINAL + Opcodes.ACC_SYNCHRONIZED
+ + Opcodes.ACC_BRIDGE + Opcodes.ACC_VARARGS + Opcodes.ACC_NATIVE
+ + Opcodes.ACC_ABSTRACT + Opcodes.ACC_STRICT
+ + Opcodes.ACC_SYNTHETIC + Opcodes.ACC_DEPRECATED);
+ CheckMethodAdapter.checkMethodIdentifier(name, "method name");
+ CheckMethodAdapter.checkMethodDesc(desc);
+ if (signature != null) {
+ CheckMethodAdapter.checkMethodSignature(signature);
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; ++i) {
+ CheckMethodAdapter.checkInternalName(exceptions[i],
+ "exception name at index " + i);
+ }
+ }
+ return new CheckMethodAdapter(cv.visitMethod(access,
+ name,
+ desc,
+ signature,
+ exceptions));
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkState();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(cv.visitAnnotation(desc, visible));
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ checkState();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ cv.visitAttribute(attr);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ public void visitEnd() {
+ checkState();
+ end = true;
+ cv.visitEnd();
+ }
+
+ /**
+ * Checks that the visit method has been called and that visitEnd has not
+ * been called.
+ */
+ private void checkState() {
+ if (!start) {
+ throw new IllegalStateException("Cannot visit member before visit has been called.");
+ }
+ if (end) {
+ throw new IllegalStateException("Cannot visit member after visitEnd has been called.");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckFieldAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckFieldAdapter.java
new file mode 100644
index 0000000..ae223b5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckFieldAdapter.java
@@ -0,0 +1,77 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that checks that its methods are properly used.
+ */
+public class CheckFieldAdapter implements FieldVisitor {
+
+ private final FieldVisitor fv;
+
+ private boolean end;
+
+ public CheckFieldAdapter(final FieldVisitor fv) {
+ this.fv = fv;
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkEnd();
+ CheckMethodAdapter.checkDesc(desc, false);
+ return new CheckAnnotationAdapter(fv.visitAnnotation(desc, visible));
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ checkEnd();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ fv.visitAttribute(attr);
+ }
+
+ public void visitEnd() {
+ checkEnd();
+ end = true;
+ fv.visitEnd();
+ }
+
+ private void checkEnd() {
+ if (end) {
+ throw new IllegalStateException("Cannot call a visit method after visitEnd has been called");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckMethodAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckMethodAdapter.java
new file mode 100644
index 0000000..ae52782
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckMethodAdapter.java
@@ -0,0 +1,1325 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodAdapter;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link MethodAdapter} that checks that its methods are properly used. More
+ * precisely this code adapter checks each instruction individually (i.e., each
+ * visit method checks some preconditions based <i>only</i> on its arguments -
+ * such as the fact that the given opcode is correct for a given visit method),
+ * but does <i>not</i> check the <i>sequence</i> of instructions. For example,
+ * in a method whose signature is <tt>void m ()</tt>, the invalid instruction
+ * IRETURN, or the invalid sequence IADD L2I will <i>not</i> be detected by
+ * this code adapter.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckMethodAdapter extends MethodAdapter {
+
+ /**
+ * Code of the visit method to be used for each opcode.
+ */
+ private static final int[] TYPE;
+
+ static {
+ String s = "BBBBBBBBBBBBBBBBCCIAADDDDDAAAAAAAAAAAAAAAAAAAABBBBBBBBDD"
+ + "DDDAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
+ + "BBBBBBBBBBBBBBBBBBBJBBBBBBBBBBBBBBBBBBBBHHHHHHHHHHHHHHHHD"
+ + "KLBBBBBBFFFFGGGGAECEBBEEBBAMHHAA";
+ TYPE = new int[s.length()];
+ for (int i = 0; i < TYPE.length; ++i) {
+ TYPE[i] = s.charAt(i) - 'A' - 1;
+ }
+ }
+
+ /**
+ * The already visited labels. This map associate Integer values to Label
+ * keys.
+ */
+ private final Map labels;
+ /**
+ * <tt>true</tt> if the visitCode method has been called.
+ */
+ private boolean startCode;
+ /**
+ * <tt>true</tt> if the visitMaxs method has been called.
+ */
+ private boolean endCode;
+ /**
+ * <tt>true</tt> if the visitEnd method has been called.
+ */
+ private boolean endMethod;
+
+ // code to generate the above string
+ // public static void main (String[] args) {
+ // int[] TYPE = new int[] {
+ // 0, //NOP
+ // 0, //ACONST_NULL
+ // 0, //ICONST_M1
+ // 0, //ICONST_0
+ // 0, //ICONST_1
+ // 0, //ICONST_2
+ // 0, //ICONST_3
+ // 0, //ICONST_4
+ // 0, //ICONST_5
+ // 0, //LCONST_0
+ // 0, //LCONST_1
+ // 0, //FCONST_0
+ // 0, //FCONST_1
+ // 0, //FCONST_2
+ // 0, //DCONST_0
+ // 0, //DCONST_1
+ // 1, //BIPUSH
+ // 1, //SIPUSH
+ // 7, //LDC
+ // -1, //LDC_W
+ // -1, //LDC2_W
+ // 2, //ILOAD
+ // 2, //LLOAD
+ // 2, //FLOAD
+ // 2, //DLOAD
+ // 2, //ALOAD
+ // -1, //ILOAD_0
+ // -1, //ILOAD_1
+ // -1, //ILOAD_2
+ // -1, //ILOAD_3
+ // -1, //LLOAD_0
+ // -1, //LLOAD_1
+ // -1, //LLOAD_2
+ // -1, //LLOAD_3
+ // -1, //FLOAD_0
+ // -1, //FLOAD_1
+ // -1, //FLOAD_2
+ // -1, //FLOAD_3
+ // -1, //DLOAD_0
+ // -1, //DLOAD_1
+ // -1, //DLOAD_2
+ // -1, //DLOAD_3
+ // -1, //ALOAD_0
+ // -1, //ALOAD_1
+ // -1, //ALOAD_2
+ // -1, //ALOAD_3
+ // 0, //IALOAD
+ // 0, //LALOAD
+ // 0, //FALOAD
+ // 0, //DALOAD
+ // 0, //AALOAD
+ // 0, //BALOAD
+ // 0, //CALOAD
+ // 0, //SALOAD
+ // 2, //ISTORE
+ // 2, //LSTORE
+ // 2, //FSTORE
+ // 2, //DSTORE
+ // 2, //ASTORE
+ // -1, //ISTORE_0
+ // -1, //ISTORE_1
+ // -1, //ISTORE_2
+ // -1, //ISTORE_3
+ // -1, //LSTORE_0
+ // -1, //LSTORE_1
+ // -1, //LSTORE_2
+ // -1, //LSTORE_3
+ // -1, //FSTORE_0
+ // -1, //FSTORE_1
+ // -1, //FSTORE_2
+ // -1, //FSTORE_3
+ // -1, //DSTORE_0
+ // -1, //DSTORE_1
+ // -1, //DSTORE_2
+ // -1, //DSTORE_3
+ // -1, //ASTORE_0
+ // -1, //ASTORE_1
+ // -1, //ASTORE_2
+ // -1, //ASTORE_3
+ // 0, //IASTORE
+ // 0, //LASTORE
+ // 0, //FASTORE
+ // 0, //DASTORE
+ // 0, //AASTORE
+ // 0, //BASTORE
+ // 0, //CASTORE
+ // 0, //SASTORE
+ // 0, //POP
+ // 0, //POP2
+ // 0, //DUP
+ // 0, //DUP_X1
+ // 0, //DUP_X2
+ // 0, //DUP2
+ // 0, //DUP2_X1
+ // 0, //DUP2_X2
+ // 0, //SWAP
+ // 0, //IADD
+ // 0, //LADD
+ // 0, //FADD
+ // 0, //DADD
+ // 0, //ISUB
+ // 0, //LSUB
+ // 0, //FSUB
+ // 0, //DSUB
+ // 0, //IMUL
+ // 0, //LMUL
+ // 0, //FMUL
+ // 0, //DMUL
+ // 0, //IDIV
+ // 0, //LDIV
+ // 0, //FDIV
+ // 0, //DDIV
+ // 0, //IREM
+ // 0, //LREM
+ // 0, //FREM
+ // 0, //DREM
+ // 0, //INEG
+ // 0, //LNEG
+ // 0, //FNEG
+ // 0, //DNEG
+ // 0, //ISHL
+ // 0, //LSHL
+ // 0, //ISHR
+ // 0, //LSHR
+ // 0, //IUSHR
+ // 0, //LUSHR
+ // 0, //IAND
+ // 0, //LAND
+ // 0, //IOR
+ // 0, //LOR
+ // 0, //IXOR
+ // 0, //LXOR
+ // 8, //IINC
+ // 0, //I2L
+ // 0, //I2F
+ // 0, //I2D
+ // 0, //L2I
+ // 0, //L2F
+ // 0, //L2D
+ // 0, //F2I
+ // 0, //F2L
+ // 0, //F2D
+ // 0, //D2I
+ // 0, //D2L
+ // 0, //D2F
+ // 0, //I2B
+ // 0, //I2C
+ // 0, //I2S
+ // 0, //LCMP
+ // 0, //FCMPL
+ // 0, //FCMPG
+ // 0, //DCMPL
+ // 0, //DCMPG
+ // 6, //IFEQ
+ // 6, //IFNE
+ // 6, //IFLT
+ // 6, //IFGE
+ // 6, //IFGT
+ // 6, //IFLE
+ // 6, //IF_ICMPEQ
+ // 6, //IF_ICMPNE
+ // 6, //IF_ICMPLT
+ // 6, //IF_ICMPGE
+ // 6, //IF_ICMPGT
+ // 6, //IF_ICMPLE
+ // 6, //IF_ACMPEQ
+ // 6, //IF_ACMPNE
+ // 6, //GOTO
+ // 6, //JSR
+ // 2, //RET
+ // 9, //TABLESWITCH
+ // 10, //LOOKUPSWITCH
+ // 0, //IRETURN
+ // 0, //LRETURN
+ // 0, //FRETURN
+ // 0, //DRETURN
+ // 0, //ARETURN
+ // 0, //RETURN
+ // 4, //GETSTATIC
+ // 4, //PUTSTATIC
+ // 4, //GETFIELD
+ // 4, //PUTFIELD
+ // 5, //INVOKEVIRTUAL
+ // 5, //INVOKESPECIAL
+ // 5, //INVOKESTATIC
+ // 5, //INVOKEINTERFACE
+ // -1, //UNUSED
+ // 3, //NEW
+ // 1, //NEWARRAY
+ // 3, //ANEWARRAY
+ // 0, //ARRAYLENGTH
+ // 0, //ATHROW
+ // 3, //CHECKCAST
+ // 3, //INSTANCEOF
+ // 0, //MONITORENTER
+ // 0, //MONITOREXIT
+ // -1, //WIDE
+ // 11, //MULTIANEWARRAY
+ // 6, //IFNULL
+ // 6, //IFNONNULL
+ // -1, //GOTO_W
+ // -1 //JSR_W
+ // };
+ // for (int i = 0; i < TYPE.length; ++i) {
+ // System.out.print((char)(TYPE[i] + 1 + 'A'));
+ // }
+ // System.out.println();
+ // }
+
+ /**
+ * Constructs a new {@link CheckMethodAdapter} object.
+ *
+ * @param cv the code visitor to which this adapter must delegate calls.
+ */
+ public CheckMethodAdapter(final MethodVisitor cv) {
+ super(cv);
+ this.labels = new HashMap();
+ }
+
+ /**
+ * Checks a stack frame value.
+ *
+ * @param value the value to be checked.
+ */
+ static void checkFrameValue(final Object value) {
+ if (value == Opcodes.TOP || value == Opcodes.INTEGER
+ || value == Opcodes.FLOAT || value == Opcodes.LONG
+ || value == Opcodes.DOUBLE || value == Opcodes.NULL
+ || value == Opcodes.UNINITIALIZED_THIS)
+ {
+ return;
+ }
+ if (value instanceof String) {
+ checkInternalName((String) value, "Invalid stack frame value");
+ return;
+ }
+ if (!(value instanceof Label)) {
+ throw new IllegalArgumentException("Invalid stack frame value: "
+ + value);
+ }
+ }
+
+ /**
+ * Checks that the type of the given opcode is equal to the given type.
+ *
+ * @param opcode the opcode to be checked.
+ * @param type the expected opcode type.
+ */
+ static void checkOpcode(final int opcode, final int type) {
+ if (opcode < 0 || opcode > 199 || TYPE[opcode] != type) {
+ throw new IllegalArgumentException("Invalid opcode: " + opcode);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed byte.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkSignedByte(final int value, final String msg) {
+ if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed byte): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is a signed short.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkSignedShort(final int value, final String msg) {
+ if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) {
+ throw new IllegalArgumentException(msg
+ + " (must be a signed short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an unsigned short.
+ *
+ * @param value the value to be checked.
+ * @param msg an message to be used in case of error.
+ */
+ static void checkUnsignedShort(final int value, final String msg) {
+ if (value < 0 || value > 65535) {
+ throw new IllegalArgumentException(msg
+ + " (must be an unsigned short): " + value);
+ }
+ }
+
+ /**
+ * Checks that the given value is an {@link Integer}, a{@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ *
+ * @param cst the value to be checked.
+ */
+ static void checkConstant(final Object cst) {
+ if (!(cst instanceof Integer) && !(cst instanceof Float)
+ && !(cst instanceof Long) && !(cst instanceof Double)
+ && !(cst instanceof String))
+ {
+ throw new IllegalArgumentException("Invalid constant: " + cst);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier.
+ *
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkIdentifier(final String name, final String msg) {
+ checkIdentifier(name, 0, -1, msg);
+ }
+
+ /**
+ * Checks that the given substring is a valid Java identifier.
+ *
+ * @param name the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param end index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkIdentifier(
+ final String name,
+ final int start,
+ final int end,
+ final String msg)
+ {
+ if (name == null || (end == -1 ? name.length() <= start : end <= start))
+ {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(start))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ int max = end == -1 ? name.length() : end;
+ for (int i = start + 1; i < max; ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be a valid Java identifier): " + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid Java identifier or is equal to
+ * '<init>' or '<clinit>'.
+ *
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkMethodIdentifier(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if ("<init>".equals(name) || "<clinit>".equals(name)) {
+ return;
+ }
+ if (!Character.isJavaIdentifierStart(name.charAt(0))) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be a '<init>', '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ for (int i = 1; i < name.length(); ++i) {
+ if (!Character.isJavaIdentifierPart(name.charAt(i))) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be '<init>' or '<clinit>' or a valid Java identifier): "
+ + name);
+ }
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid internal class name.
+ *
+ * @param name the string to be checked.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkInternalName(final String name, final String msg) {
+ if (name == null || name.length() == 0) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null or empty)");
+ }
+ if (name.charAt(0) == '[') {
+ checkDesc(name, false);
+ } else {
+ checkInternalName(name, 0, -1, msg);
+ }
+ }
+
+ /**
+ * Checks that the given substring is a valid internal class name.
+ *
+ * @param name the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param end index of the last character of the identifier (exclusive). -1
+ * is equivalent to <tt>name.length()</tt> if name is not
+ * <tt>null</tt>.
+ * @param msg a message to be used in case of error.
+ */
+ static void checkInternalName(
+ final String name,
+ final int start,
+ final int end,
+ final String msg)
+ {
+ int max = end == -1 ? name.length() : end;
+ try {
+ int begin = start;
+ int slash;
+ do {
+ slash = name.indexOf('/', begin + 1);
+ if (slash == -1 || slash > max) {
+ slash = max;
+ }
+ checkIdentifier(name, begin, slash, null);
+ begin = slash + 1;
+ } while (slash != max);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException("Invalid "
+ + msg
+ + " (must be a fully qualified class name in internal form): "
+ + name);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid type descriptor.
+ *
+ * @param desc the string to be checked.
+ * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+ */
+ static void checkDesc(final String desc, final boolean canBeVoid) {
+ int end = checkDesc(desc, 0, canBeVoid);
+ if (end != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks that a the given substring is a valid type descriptor.
+ *
+ * @param desc the string to be checked.
+ * @param start index of the first character of the identifier (inclusive).
+ * @param canBeVoid <tt>true</tt> if <tt>V</tt> can be considered valid.
+ * @return the index of the last character of the type decriptor, plus one.
+ */
+ static int checkDesc(
+ final String desc,
+ final int start,
+ final boolean canBeVoid)
+ {
+ if (desc == null || start >= desc.length()) {
+ throw new IllegalArgumentException("Invalid type descriptor (must not be null or empty)");
+ }
+ int index;
+ switch (desc.charAt(start)) {
+ case 'V':
+ if (canBeVoid) {
+ return start + 1;
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return start + 1;
+ case '[':
+ index = start + 1;
+ while (index < desc.length() && desc.charAt(index) == '[') {
+ ++index;
+ }
+ if (index < desc.length()) {
+ return checkDesc(desc, index, false);
+ } else {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ case 'L':
+ index = desc.indexOf(';', start);
+ if (index == -1 || index - start < 2) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ try {
+ checkInternalName(desc, start + 1, index, null);
+ } catch (IllegalArgumentException _) {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ return index + 1;
+ default:
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ }
+
+ /**
+ * Checks that the given string is a valid method descriptor.
+ *
+ * @param desc the string to be checked.
+ */
+ static void checkMethodDesc(final String desc) {
+ if (desc == null || desc.length() == 0) {
+ throw new IllegalArgumentException("Invalid method descriptor (must not be null or empty)");
+ }
+ if (desc.charAt(0) != '(' || desc.length() < 3) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ int start = 1;
+ if (desc.charAt(start) != ')') {
+ do {
+ if (desc.charAt(start) == 'V') {
+ throw new IllegalArgumentException("Invalid descriptor: "
+ + desc);
+ }
+ start = checkDesc(desc, start, false);
+ } while (start < desc.length() && desc.charAt(start) != ')');
+ }
+ start = checkDesc(desc, start + 1, true);
+ if (start != desc.length()) {
+ throw new IllegalArgumentException("Invalid descriptor: " + desc);
+ }
+ }
+
+ /**
+ * Checks a class signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkClassSignature(final String signature) {
+ // ClassSignature:
+ // FormalTypeParameters? ClassTypeSignature ClassTypeSignature*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkClassTypeSignature(signature, pos);
+ while (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkMethodSignature(final String signature) {
+ // MethodTypeSignature:
+ // FormalTypeParameters? ( TypeSignature* ) ( TypeSignature | V ) (
+ // ^ClassTypeSignature | ^TypeVariableSignature )*
+
+ int pos = 0;
+ if (getChar(signature, 0) == '<') {
+ pos = checkFormalTypeParameters(signature, pos);
+ }
+ pos = checkChar('(', signature, pos);
+ while ("ZCBSIFJDL[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkTypeSignature(signature, pos);
+ }
+ pos = checkChar(')', signature, pos);
+ if (getChar(signature, pos) == 'V') {
+ ++pos;
+ } else {
+ pos = checkTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == '^') {
+ ++pos;
+ if (getChar(signature, pos) == 'L') {
+ pos = checkClassTypeSignature(signature, pos);
+ } else {
+ pos = checkTypeVariableSignature(signature, pos);
+ }
+ }
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks a field signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ */
+ static void checkFieldSignature(final String signature) {
+ int pos = checkFieldTypeSignature(signature, 0);
+ if (pos != signature.length()) {
+ throw new IllegalArgumentException(signature + ": error at index "
+ + pos);
+ }
+ }
+
+ /**
+ * Checks the formal type parameters of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameters(final String signature, int pos)
+ {
+ // FormalTypeParameters:
+ // < FormalTypeParameter+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkFormalTypeParameter(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkFormalTypeParameter(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a formal type parameter of a class or method signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFormalTypeParameter(final String signature, int pos)
+ {
+ // FormalTypeParameter:
+ // Identifier : FieldTypeSignature? (: FieldTypeSignature)*
+
+ pos = checkIdentifier(signature, pos);
+ pos = checkChar(':', signature, pos);
+ if ("L[T".indexOf(getChar(signature, pos)) != -1) {
+ pos = checkFieldTypeSignature(signature, pos);
+ }
+ while (getChar(signature, pos) == ':') {
+ pos = checkFieldTypeSignature(signature, pos + 1);
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a field type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkFieldTypeSignature(final String signature, int pos)
+ {
+ // FieldTypeSignature:
+ // ClassTypeSignature | ArrayTypeSignature | TypeVariableSignature
+ //
+ // ArrayTypeSignature:
+ // [ TypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'L':
+ return checkClassTypeSignature(signature, pos);
+ case '[':
+ return checkTypeSignature(signature, pos + 1);
+ default:
+ return checkTypeVariableSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkClassTypeSignature(final String signature, int pos)
+ {
+ // ClassTypeSignature:
+ // L Identifier ( / Identifier )* TypeArguments? ( . Identifier
+ // TypeArguments? )* ;
+
+ pos = checkChar('L', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ while (getChar(signature, pos) == '/') {
+ pos = checkIdentifier(signature, pos + 1);
+ }
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ while (getChar(signature, pos) == '.') {
+ pos = checkIdentifier(signature, pos + 1);
+ if (getChar(signature, pos) == '<') {
+ pos = checkTypeArguments(signature, pos);
+ }
+ }
+ return checkChar(';', signature, pos);
+ }
+
+ /**
+ * Checks the type arguments in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArguments(final String signature, int pos) {
+ // TypeArguments:
+ // < TypeArgument+ >
+
+ pos = checkChar('<', signature, pos);
+ pos = checkTypeArgument(signature, pos);
+ while (getChar(signature, pos) != '>') {
+ pos = checkTypeArgument(signature, pos);
+ }
+ return pos + 1;
+ }
+
+ /**
+ * Checks a type argument in a class type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeArgument(final String signature, int pos) {
+ // TypeArgument:
+ // * | ( ( + | - )? FieldTypeSignature )
+
+ char c = getChar(signature, pos);
+ if (c == '*') {
+ return pos + 1;
+ } else if (c == '+' || c == '-') {
+ pos++;
+ }
+ return checkFieldTypeSignature(signature, pos);
+ }
+
+ /**
+ * Checks a type variable signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeVariableSignature(
+ final String signature,
+ int pos)
+ {
+ // TypeVariableSignature:
+ // T Identifier ;
+
+ pos = checkChar('T', signature, pos);
+ pos = checkIdentifier(signature, pos);
+ return checkChar(';', signature, pos);
+ }
+
+ // -------------------------------------------------------------------------
+
+ /**
+ * Checks a type signature.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkTypeSignature(final String signature, int pos) {
+ // TypeSignature:
+ // Z | C | B | S | I | F | J | D | FieldTypeSignature
+
+ switch (getChar(signature, pos)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ case 'F':
+ case 'J':
+ case 'D':
+ return pos + 1;
+ default:
+ return checkFieldTypeSignature(signature, pos);
+ }
+ }
+
+ /**
+ * Checks an identifier.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkIdentifier(final String signature, int pos) {
+ if (!Character.isJavaIdentifierStart(getChar(signature, pos))) {
+ throw new IllegalArgumentException(signature
+ + ": identifier expected at index " + pos);
+ }
+ ++pos;
+ while (Character.isJavaIdentifierPart(getChar(signature, pos))) {
+ ++pos;
+ }
+ return pos;
+ }
+
+ /**
+ * Checks a single character.
+ *
+ * @param signature a string containing the signature that must be checked.
+ * @param pos index of first character to be checked.
+ * @return the index of the first character after the checked part.
+ */
+ private static int checkChar(final char c, final String signature, int pos)
+ {
+ if (getChar(signature, pos) == c) {
+ return pos + 1;
+ }
+ throw new IllegalArgumentException(signature + ": '" + c
+ + "' expected at index " + pos);
+ }
+
+ /**
+ * Returns the signature car at the given index.
+ *
+ * @param signature a signature.
+ * @param pos an index in signature.
+ * @return the character at the given index, or 0 if there is no such
+ * character.
+ */
+ private static char getChar(final String signature, int pos) {
+ return pos < signature.length() ? signature.charAt(pos) : (char) 0;
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(mv.visitAnnotation(desc, visible));
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ checkEndMethod();
+ return new CheckAnnotationAdapter(mv.visitAnnotationDefault(), false);
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ checkEndMethod();
+ checkDesc(desc, false);
+ return new CheckAnnotationAdapter(mv.visitParameterAnnotation(parameter,
+ desc,
+ visible));
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ checkEndMethod();
+ if (attr == null) {
+ throw new IllegalArgumentException("Invalid attribute (must not be null)");
+ }
+ mv.visitAttribute(attr);
+ }
+
+ public void visitCode() {
+ startCode = true;
+ mv.visitCode();
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ int mLocal;
+ int mStack;
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ mLocal = Integer.MAX_VALUE;
+ mStack = Integer.MAX_VALUE;
+ break;
+
+ case Opcodes.F_SAME:
+ mLocal = 0;
+ mStack = 0;
+ break;
+
+ case Opcodes.F_SAME1:
+ mLocal = 0;
+ mStack = 1;
+ break;
+
+ case Opcodes.F_APPEND:
+ case Opcodes.F_CHOP:
+ mLocal = 3;
+ mStack = 0;
+ break;
+
+ default:
+ throw new IllegalArgumentException("Invalid frame type " + type);
+ }
+
+ if (nLocal > mLocal) {
+ throw new IllegalArgumentException("Invalid nLocal=" + nLocal
+ + " for frame type " + type);
+ }
+ if (nStack > mStack) {
+ throw new IllegalArgumentException("Invalid nStack=" + nStack
+ + " for frame type " + type);
+ }
+
+ if (type != Opcodes.F_CHOP) {
+ if (nLocal > 0 && (local == null || local.length < nLocal)) {
+ throw new IllegalArgumentException("Array local[] is shorter than nLocal");
+ }
+ for (int i = 0; i < nLocal; ++i) {
+ checkFrameValue(local[i]);
+ }
+ }
+ if (nStack > 0 && (stack == null || stack.length < nStack)) {
+ throw new IllegalArgumentException("Array stack[] is shorter than nStack");
+ }
+ for (int i = 0; i < nStack; ++i) {
+ checkFrameValue(stack[i]);
+ }
+
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ public void visitInsn(final int opcode) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 0);
+ mv.visitInsn(opcode);
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 1);
+ switch (opcode) {
+ case Opcodes.BIPUSH:
+ checkSignedByte(operand, "Invalid operand");
+ break;
+ case Opcodes.SIPUSH:
+ checkSignedShort(operand, "Invalid operand");
+ break;
+ // case Constants.NEWARRAY:
+ default:
+ if (operand < Opcodes.T_BOOLEAN || operand > Opcodes.T_LONG) {
+ throw new IllegalArgumentException("Invalid operand (must be an array type code T_...): "
+ + operand);
+ }
+ }
+ mv.visitIntInsn(opcode, operand);
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 2);
+ checkUnsignedShort(var, "Invalid variable index");
+ mv.visitVarInsn(opcode, var);
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 3);
+ checkInternalName(type, "type");
+ if (opcode == Opcodes.NEW && type.charAt(0) == '[') {
+ throw new IllegalArgumentException("NEW cannot be used to create arrays: "
+ + type);
+ }
+ mv.visitTypeInsn(opcode, type);
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 4);
+ checkInternalName(owner, "owner");
+ checkIdentifier(name, "name");
+ checkDesc(desc, false);
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 5);
+ checkMethodIdentifier(name, "name");
+ checkInternalName(owner, "owner");
+ checkMethodDesc(desc);
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkOpcode(opcode, 6);
+ checkLabel(label, false, "label");
+ mv.visitJumpInsn(opcode, label);
+ }
+
+ public void visitLabel(final Label label) {
+ checkStartCode();
+ checkEndCode();
+ checkLabel(label, false, "label");
+ if (labels.get(label) != null) {
+ throw new IllegalArgumentException("Already visited label");
+ }
+ labels.put(label, new Integer(labels.size()));
+ mv.visitLabel(label);
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ checkStartCode();
+ checkEndCode();
+ if (!(cst instanceof Type)) {
+ checkConstant(cst);
+ }
+ mv.visitLdcInsn(cst);
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(var, "Invalid variable index");
+ checkSignedShort(increment, "Invalid increment");
+ mv.visitIincInsn(var, increment);
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ checkStartCode();
+ checkEndCode();
+ if (max < min) {
+ throw new IllegalArgumentException("Max = " + max
+ + " must be greater than or equal to min = " + min);
+ }
+ checkLabel(dflt, false, "default label");
+ if (labels == null || labels.length != max - min + 1) {
+ throw new IllegalArgumentException("There must be max - min + 1 labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ }
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ checkEndCode();
+ checkStartCode();
+ checkLabel(dflt, false, "default label");
+ if (keys == null || labels == null || keys.length != labels.length) {
+ throw new IllegalArgumentException("There must be the same number of keys and labels");
+ }
+ for (int i = 0; i < labels.length; ++i) {
+ checkLabel(labels[i], false, "label at index " + i);
+ }
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ checkStartCode();
+ checkEndCode();
+ checkDesc(desc, false);
+ if (desc.charAt(0) != '[') {
+ throw new IllegalArgumentException("Invalid descriptor (must be an array type descriptor): "
+ + desc);
+ }
+ if (dims < 1) {
+ throw new IllegalArgumentException("Invalid dimensions (must be greater than 0): "
+ + dims);
+ }
+ if (dims > desc.lastIndexOf('[') + 1) {
+ throw new IllegalArgumentException("Invalid dimensions (must not be greater than dims(desc)): "
+ + dims);
+ }
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ checkStartCode();
+ checkEndCode();
+ if (type != null) {
+ checkInternalName(type, "type");
+ }
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ checkStartCode();
+ checkEndCode();
+ checkIdentifier(name, "name");
+ checkDesc(desc, false);
+ checkLabel(start, true, "start label");
+ checkLabel(end, true, "end label");
+ checkUnsignedShort(index, "Invalid variable index");
+ int s = ((Integer) labels.get(start)).intValue();
+ int e = ((Integer) labels.get(end)).intValue();
+ if (e < s) {
+ throw new IllegalArgumentException("Invalid start and end labels (end must be greater than start)");
+ }
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ checkStartCode();
+ checkEndCode();
+ checkUnsignedShort(line, "Invalid line number");
+ checkLabel(start, true, "start label");
+ mv.visitLineNumber(line, start);
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ checkStartCode();
+ checkEndCode();
+ endCode = true;
+ checkUnsignedShort(maxStack, "Invalid max stack");
+ checkUnsignedShort(maxLocals, "Invalid max locals");
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+
+ public void visitEnd() {
+ checkEndMethod();
+ endMethod = true;
+ mv.visitEnd();
+ }
+
+ /**
+ * Checks that the visitCode method has been called.
+ */
+ void checkStartCode() {
+ if (!startCode) {
+ throw new IllegalStateException("Cannot visit instructions before visitCode has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitMaxs method has not been called.
+ */
+ void checkEndCode() {
+ if (endCode) {
+ throw new IllegalStateException("Cannot visit instructions after visitMaxs has been called.");
+ }
+ }
+
+ /**
+ * Checks that the visitEnd method has not been called.
+ */
+ void checkEndMethod() {
+ if (endMethod) {
+ throw new IllegalStateException("Cannot visit elements after visitEnd has been called.");
+ }
+ }
+
+ /**
+ * Checks that the given label is not null. This method can also check that
+ * the label has been visited.
+ *
+ * @param label the label to be checked.
+ * @param checkVisited <tt>true</tt> to check that the label has been
+ * visited.
+ * @param msg a message to be used in case of error.
+ */
+ void checkLabel(
+ final Label label,
+ final boolean checkVisited,
+ final String msg)
+ {
+ if (label == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must not be null)");
+ }
+ if (checkVisited && labels.get(label) == null) {
+ throw new IllegalArgumentException("Invalid " + msg
+ + " (must be visited first)");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckSignatureAdapter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckSignatureAdapter.java
new file mode 100644
index 0000000..ce14d31
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/CheckSignatureAdapter.java
@@ -0,0 +1,287 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that checks that its methods are properly used.
+ *
+ * @author Eric Bruneton
+ */
+public class CheckSignatureAdapter implements SignatureVisitor {
+
+ /**
+ * Type to be used to check class signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int CLASS_SIGNATURE = 0;
+
+ /**
+ * Type to be used to check method signatures. See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int METHOD_SIGNATURE = 1;
+
+ /**
+ * Type to be used to check type signatures.See
+ * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
+ */
+ public static final int TYPE_SIGNATURE = 2;
+
+ private static final int EMPTY = 1;
+
+ private static final int FORMAL = 2;
+
+ private static final int BOUND = 4;
+
+ private static final int SUPER = 8;
+
+ private static final int PARAM = 16;
+
+ private static final int RETURN = 32;
+
+ private static final int SIMPLE_TYPE = 64;
+
+ private static final int CLASS_TYPE = 128;
+
+ private static final int END = 256;
+
+ /**
+ * Type of the signature to be checked.
+ */
+ private final int type;
+ /**
+ * The visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ private final SignatureVisitor sv;
+ /**
+ * State of the automaton used to check the order of method calls.
+ */
+ private int state;
+ /**
+ * <tt>true</tt> if the checked type signature can be 'V'.
+ */
+ private boolean canBeVoid;
+
+ /**
+ * Creates a new {@link CheckSignatureAdapter} object.
+ *
+ * @param type the type of signature to be checked. See
+ * {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
+ * {@link #TYPE_SIGNATURE}.
+ * @param sv the visitor to which this adapter must delegate calls. May be
+ * <tt>null</tt>.
+ */
+ public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
+ this.type = type;
+ this.state = EMPTY;
+ this.sv = sv;
+ }
+
+ // class and method signatures
+
+ public void visitFormalTypeParameter(final String name) {
+ if (type == TYPE_SIGNATURE
+ || (state != EMPTY && state != FORMAL && state != BOUND))
+ {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
+ state = FORMAL;
+ if (sv != null) {
+ sv.visitFormalTypeParameter(name);
+ }
+ }
+
+ public SignatureVisitor visitClassBound() {
+ if (state != FORMAL) {
+ throw new IllegalStateException();
+ }
+ state = BOUND;
+ SignatureVisitor v = sv == null ? null : sv.visitClassBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ public SignatureVisitor visitInterfaceBound() {
+ if (state != FORMAL && state != BOUND) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // class signatures
+
+ public SignatureVisitor visitSuperclass() {
+ if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = SUPER;
+ SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ public SignatureVisitor visitInterface() {
+ if (state != SUPER) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitInterface();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // method signatures
+
+ public SignatureVisitor visitParameterType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = PARAM;
+ SignatureVisitor v = sv == null ? null : sv.visitParameterType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ public SignatureVisitor visitReturnType() {
+ if (type != METHOD_SIGNATURE
+ || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
+ {
+ throw new IllegalArgumentException();
+ }
+ state = RETURN;
+ SignatureVisitor v = sv == null ? null : sv.visitReturnType();
+ CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ cv.canBeVoid = true;
+ return cv;
+ }
+
+ public SignatureVisitor visitExceptionType() {
+ if (state != RETURN) {
+ throw new IllegalStateException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ // type signatures
+
+ public void visitBaseType(final char descriptor) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ if (descriptor == 'V') {
+ if (!canBeVoid) {
+ throw new IllegalArgumentException();
+ }
+ } else {
+ if ("ZCBSIFJD".indexOf(descriptor) == -1) {
+ throw new IllegalArgumentException();
+ }
+ }
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitBaseType(descriptor);
+ }
+ }
+
+ public void visitTypeVariable(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "type variable");
+ state = SIMPLE_TYPE;
+ if (sv != null) {
+ sv.visitTypeVariable(name);
+ }
+ }
+
+ public SignatureVisitor visitArrayType() {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ state = SIMPLE_TYPE;
+ SignatureVisitor v = sv == null ? null : sv.visitArrayType();
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ public void visitClassType(final String name) {
+ if (type != TYPE_SIGNATURE || state != EMPTY) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkInternalName(name, "class name");
+ state = CLASS_TYPE;
+ if (sv != null) {
+ sv.visitClassType(name);
+ }
+ }
+
+ public void visitInnerClassType(final String name) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ CheckMethodAdapter.checkIdentifier(name, "inner class name");
+ if (sv != null) {
+ sv.visitInnerClassType(name);
+ }
+ }
+
+ public void visitTypeArgument() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if (sv != null) {
+ sv.visitTypeArgument();
+ }
+ }
+
+ public SignatureVisitor visitTypeArgument(final char wildcard) {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ if ("+-=".indexOf(wildcard) == -1) {
+ throw new IllegalArgumentException();
+ }
+ SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
+ return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
+ }
+
+ public void visitEnd() {
+ if (state != CLASS_TYPE) {
+ throw new IllegalStateException();
+ }
+ state = END;
+ if (sv != null) {
+ sv.visitEnd();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAbstractVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAbstractVisitor.java
new file mode 100644
index 0000000..22740c2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAbstractVisitor.java
@@ -0,0 +1,179 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+
+/**
+ * An abstract trace visitor.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class TraceAbstractVisitor extends AbstractVisitor {
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for internal
+ * type names in bytecode notation.
+ */
+ public static final int INTERNAL_NAME = 0;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int FIELD_DESCRIPTOR = 1;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field
+ * signatures, formatted in bytecode notation
+ */
+ public static final int FIELD_SIGNATURE = 2;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * descriptors, formatted in bytecode notation
+ */
+ public static final int METHOD_DESCRIPTOR = 3;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * signatures, formatted in bytecode notation
+ */
+ public static final int METHOD_SIGNATURE = 4;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in bytecode notation
+ */
+ public static final int CLASS_SIGNATURE = 5;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for field or
+ * method return value signatures, formatted in default Java notation
+ * (non-bytecode)
+ */
+ public static final int TYPE_DECLARATION = 6;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for class
+ * signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int CLASS_DECLARATION = 7;
+
+ /**
+ * Constant used in {@link #appendDescriptor appendDescriptor} for method
+ * parameter signatures, formatted in default Java notation (non-bytecode)
+ */
+ public static final int PARAMETERS_DECLARATION = 8;
+
+ /**
+ * Tab for class members.
+ */
+ protected String tab = " ";
+
+ /**
+ * Prints a disassembled view of the given annotation.
+ *
+ * @param desc the class descriptor of the annotation class.
+ * @param visible <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values.
+ */
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append(tab).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+ text.add(tav.getText());
+ text.add(visible ? ")\n" : ") // invisible\n");
+ return tav;
+ }
+
+ /**
+ * Prints a disassembled view of the given attribute.
+ *
+ * @param attr an attribute.
+ */
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Traceable) {
+ ((Traceable) attr).trace(buf, null);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ }
+
+ /**
+ * Does nothing.
+ */
+ public void visitEnd() {
+ // does nothing
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ protected TraceAnnotationVisitor createTraceAnnotationVisitor() {
+ return new TraceAnnotationVisitor();
+ }
+
+ /**
+ * Appends an internal name, a type descriptor or a type signature to
+ * {@link #buf buf}.
+ *
+ * @param type indicates if desc is an internal name, a field descriptor, a
+ * method descriptor, a class signature, ...
+ * @param desc an internal name, type descriptor, or type signature. May be
+ * <tt>null</tt>.
+ */
+ protected void appendDescriptor(final int type, final String desc) {
+ if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE
+ || type == METHOD_SIGNATURE)
+ {
+ if (desc != null) {
+ buf.append("// signature ").append(desc).append('\n');
+ }
+ } else {
+ buf.append(desc);
+ }
+ }
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAnnotationVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAnnotationVisitor.java
new file mode 100644
index 0000000..4b25c88
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceAnnotationVisitor.java
@@ -0,0 +1,266 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * An {@link AnnotationVisitor} that prints a disassembled view of the
+ * annotations it visits.
+ *
+ * @author Eric Bruneton
+ */
+public class TraceAnnotationVisitor extends TraceAbstractVisitor implements
+ AnnotationVisitor
+{
+
+ /**
+ * The {@link AnnotationVisitor} to which this visitor delegates calls. May
+ * be <tt>null</tt>.
+ */
+ protected AnnotationVisitor av;
+
+ private int valueNumber = 0;
+
+ /**
+ * Constructs a new {@link TraceAnnotationVisitor}.
+ */
+ public TraceAnnotationVisitor() {
+ // ignore
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(final String name, final Object value) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+
+ if (value instanceof String) {
+ visitString((String) value);
+ } else if (value instanceof Type) {
+ visitType((Type) value);
+ } else if (value instanceof Byte) {
+ visitByte(((Byte) value).byteValue());
+ } else if (value instanceof Boolean) {
+ visitBoolean(((Boolean) value).booleanValue());
+ } else if (value instanceof Short) {
+ visitShort(((Short) value).shortValue());
+ } else if (value instanceof Character) {
+ visitChar(((Character) value).charValue());
+ } else if (value instanceof Integer) {
+ visitInt(((Integer) value).intValue());
+ } else if (value instanceof Float) {
+ visitFloat(((Float) value).floatValue());
+ } else if (value instanceof Long) {
+ visitLong(((Long) value).longValue());
+ } else if (value instanceof Double) {
+ visitDouble(((Double) value).doubleValue());
+ } else if (value.getClass().isArray()) {
+ buf.append('{');
+ if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitByte(v[i]);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitBoolean(v[i]);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitShort(v[i]);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitChar(v[i]);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitInt(v[i]);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitLong(v[i]);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitFloat(v[i]);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ for (int i = 0; i < v.length; i++) {
+ appendComa(i);
+ visitDouble(v[i]);
+ }
+ }
+ buf.append('}');
+ }
+
+ text.add(buf.toString());
+
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ private void visitInt(final int value) {
+ buf.append(value);
+ }
+
+ private void visitLong(final long value) {
+ buf.append(value).append('L');
+ }
+
+ private void visitFloat(final float value) {
+ buf.append(value).append('F');
+ }
+
+ private void visitDouble(final double value) {
+ buf.append(value).append('D');
+ }
+
+ private void visitChar(final char value) {
+ buf.append("(char)").append((int) value);
+ }
+
+ private void visitShort(final short value) {
+ buf.append("(short)").append(value);
+ }
+
+ private void visitByte(final byte value) {
+ buf.append("(byte)").append(value);
+ }
+
+ private void visitBoolean(final boolean value) {
+ buf.append(value);
+ }
+
+ private void visitString(final String value) {
+ appendString(buf, value);
+ }
+
+ private void visitType(final Type value) {
+ buf.append(value.getClassName()).append(".class");
+ }
+
+ public void visitEnum(
+ final String name,
+ final String desc,
+ final String value)
+ {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('.').append(value);
+ text.add(buf.toString());
+
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+ text.add(tav.getText());
+ text.add(")");
+ if (av != null) {
+ tav.av = av.visitAnnotation(name, desc);
+ }
+ return tav;
+ }
+
+ public AnnotationVisitor visitArray(final String name) {
+ buf.setLength(0);
+ appendComa(valueNumber++);
+ if (name != null) {
+ buf.append(name).append('=');
+ }
+ buf.append('{');
+ text.add(buf.toString());
+ TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+ text.add(tav.getText());
+ text.add("}");
+ if (av != null) {
+ tav.av = av.visitArray(name);
+ }
+ return tav;
+ }
+
+ public void visitEnd() {
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ private void appendComa(final int i) {
+ if (i != 0) {
+ buf.append(", ");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceClassVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceClassVisitor.java
new file mode 100644
index 0000000..89b2508
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceClassVisitor.java
@@ -0,0 +1,523 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.signature.SignatureReader;
+
+import java.io.FileInputStream;
+import java.io.PrintWriter;
+
+/**
+ * A {@link ClassVisitor} that prints a disassembled view of the classes it
+ * visits. This class visitor can be used alone (see the {@link #main main}
+ * method) to disassemble a class. It can also be used in the middle of class
+ * visitor chain to trace the class that is visited at a given point in this
+ * chain. This may be uselful for debugging purposes. <p> The trace printed when
+ * visiting the <tt>Hello</tt> class is the following: <p> <blockquote>
+ *
+ * <pre>
+ * // class version 49.0 (49)
+ * // access flags 33
+ * public class Hello {
+ *
+ * // compiled from: Hello.java
+ *
+ * // access flags 1
+ * public <init> ()V
+ * ALOAD 0
+ * INVOKESPECIAL java/lang/Object <init> ()V
+ * RETURN
+ * MAXSTACK = 1
+ * MAXLOCALS = 1
+ *
+ * // access flags 9
+ * public static main ([Ljava/lang/String;)V
+ * GETSTATIC java/lang/System out Ljava/io/PrintStream;
+ * LDC "hello"
+ * INVOKEVIRTUAL java/io/PrintStream println (Ljava/lang/String;)V
+ * RETURN
+ * MAXSTACK = 2
+ * MAXLOCALS = 1
+ * }
+ * </pre>
+ *
+ * </blockquote> where <tt>Hello</tt> is defined by: <p> <blockquote>
+ *
+ * <pre>
+ * public class Hello {
+ *
+ * public static void main(String[] args) {
+ * System.out.println("hello");
+ * }
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class TraceClassVisitor extends TraceAbstractVisitor implements
+ ClassVisitor
+{
+
+ /**
+ * The {@link ClassVisitor} to which this visitor delegates calls. May be
+ * <tt>null</tt>.
+ */
+ protected final ClassVisitor cv;
+
+ /**
+ * The print writer to be used to print the class.
+ */
+ protected final PrintWriter pw;
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final PrintWriter pw) {
+ this(null, pw);
+ }
+
+ /**
+ * Constructs a new {@link TraceClassVisitor}.
+ *
+ * @param cv the {@link ClassVisitor} to which this visitor delegates calls.
+ * May be <tt>null</tt>.
+ * @param pw the print writer to be used to print the class.
+ */
+ public TraceClassVisitor(final ClassVisitor cv, final PrintWriter pw) {
+ this.cv = cv;
+ this.pw = pw;
+ }
+
+ /**
+ * Prints a disassembled view of the given class to the standard output. <p>
+ * Usage: TraceClassVisitor [-debug] <fully qualified class name or class
+ * file name >
+ *
+ * @param args the command line arguments.
+ *
+ * @throws Exception if the class cannot be found, or if an IO exception
+ * occurs.
+ */
+ public static void main(final String[] args) throws Exception {
+ int i = 0;
+ int flags = ClassReader.SKIP_DEBUG;
+
+ boolean ok = true;
+ if (args.length < 1 || args.length > 2) {
+ ok = false;
+ }
+ if (ok && "-debug".equals(args[0])) {
+ i = 1;
+ flags = 0;
+ if (args.length != 2) {
+ ok = false;
+ }
+ }
+ if (!ok) {
+ System.err.println("Prints a disassembled view of the given class.");
+ System.err.println("Usage: TraceClassVisitor [-debug] "
+ + "<fully qualified class name or class file name>");
+ return;
+ }
+ ClassReader cr;
+ if (args[i].endsWith(".class") || args[i].indexOf('\\') > -1
+ || args[i].indexOf('/') > -1)
+ {
+ cr = new ClassReader(new FileInputStream(args[i]));
+ } else {
+ cr = new ClassReader(args[i]);
+ }
+ cr.accept(new TraceClassVisitor(new PrintWriter(System.out)),
+ getDefaultAttributes(),
+ flags);
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor interface
+ // ------------------------------------------------------------------------
+
+ public void visit(
+ final int version,
+ final int access,
+ final String name,
+ final String signature,
+ final String superName,
+ final String[] interfaces)
+ {
+ int major = version & 0xFFFF;
+ int minor = version >>> 16;
+ buf.setLength(0);
+ buf.append("// class version ")
+ .append(major)
+ .append('.')
+ .append(minor)
+ .append(" (")
+ .append(version)
+ .append(")\n");
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append("// DEPRECATED\n");
+ }
+ buf.append("// access flags ").append(access).append('\n');
+
+ appendDescriptor(CLASS_SIGNATURE, signature);
+ if (signature != null) {
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(sv);
+ buf.append("// declaration: ")
+ .append(name)
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ appendAccess(access & ~Opcodes.ACC_SUPER);
+ if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+ buf.append("@interface ");
+ } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+ buf.append("interface ");
+ } else if ((access & Opcodes.ACC_ENUM) == 0) {
+ buf.append("class ");
+ }
+ appendDescriptor(INTERNAL_NAME, name);
+
+ if (superName != null && !"java/lang/Object".equals(superName)) {
+ buf.append(" extends ");
+ appendDescriptor(INTERNAL_NAME, superName);
+ buf.append(' ');
+ }
+ if (interfaces != null && interfaces.length > 0) {
+ buf.append(" implements ");
+ for (int i = 0; i < interfaces.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, interfaces[i]);
+ buf.append(' ');
+ }
+ }
+ buf.append(" {\n\n");
+
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+ }
+
+ public void visitSource(final String file, final String debug) {
+ buf.setLength(0);
+ if (file != null) {
+ buf.append(tab)
+ .append("// compiled from: ")
+ .append(file)
+ .append('\n');
+ }
+ if (debug != null) {
+ buf.append(tab)
+ .append("// debug info: ")
+ .append(debug)
+ .append('\n');
+ }
+ if (buf.length() > 0) {
+ text.add(buf.toString());
+ }
+
+ if (cv != null) {
+ cv.visitSource(file, debug);
+ }
+ }
+
+ public void visitOuterClass(
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("OUTERCLASS ");
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append(' ');
+ if (name != null) {
+ buf.append(name).append(' ');
+ }
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ text.add("\n");
+ AnnotationVisitor tav = super.visitAnnotation(desc, visible);
+ if (cv != null) {
+ ((TraceAnnotationVisitor) tav).av = cv.visitAnnotation(desc,
+ visible);
+ }
+ return tav;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ text.add("\n");
+ super.visitAttribute(attr);
+
+ if (cv != null) {
+ cv.visitAttribute(attr);
+ }
+ }
+
+ public void visitInnerClass(
+ final String name,
+ final String outerName,
+ final String innerName,
+ final int access)
+ {
+ buf.setLength(0);
+ buf.append(tab).append("// access flags ");
+ buf.append(access & ~Opcodes.ACC_SUPER).append('\n');
+ buf.append(tab);
+ appendAccess(access);
+ buf.append("INNERCLASS ");
+ appendDescriptor(INTERNAL_NAME, name);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, outerName);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, innerName);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (cv != null) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ public FieldVisitor visitField(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final Object value)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags ").append(access).append('\n');
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(name);
+ if (value != null) {
+ buf.append(" = ");
+ if (value instanceof String) {
+ buf.append('\"').append(value).append('\"');
+ } else {
+ buf.append(value);
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ TraceFieldVisitor tav = createTraceFieldVisitor();
+ text.add(tav.getText());
+
+ if (cv != null) {
+ tav.fv = cv.visitField(access, name, desc, signature, value);
+ }
+
+ return tav;
+ }
+
+ public MethodVisitor visitMethod(
+ final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions)
+ {
+ buf.setLength(0);
+ buf.append('\n');
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ buf.append(tab).append("// DEPRECATED\n");
+ }
+ buf.append(tab).append("// access flags ").append(access).append('\n');
+
+ if (signature != null) {
+ buf.append(tab);
+ appendDescriptor(METHOD_SIGNATURE, signature);
+
+ TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.accept(v);
+ String genericDecl = v.getDeclaration();
+ String genericReturn = v.getReturnType();
+ String genericExceptions = v.getExceptions();
+
+ buf.append(tab)
+ .append("// declaration: ")
+ .append(genericReturn)
+ .append(' ')
+ .append(name)
+ .append(genericDecl);
+ if (genericExceptions != null) {
+ buf.append(" throws ").append(genericExceptions);
+ }
+ buf.append('\n');
+ }
+
+ buf.append(tab);
+ appendAccess(access);
+ if ((access & Opcodes.ACC_NATIVE) != 0) {
+ buf.append("native ");
+ }
+ if ((access & Opcodes.ACC_VARARGS) != 0) {
+ buf.append("varargs ");
+ }
+ if ((access & Opcodes.ACC_BRIDGE) != 0) {
+ buf.append("bridge ");
+ }
+
+ buf.append(name);
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ if (exceptions != null && exceptions.length > 0) {
+ buf.append(" throws ");
+ for (int i = 0; i < exceptions.length; ++i) {
+ appendDescriptor(INTERNAL_NAME, exceptions[i]);
+ buf.append(' ');
+ }
+ }
+
+ buf.append('\n');
+ text.add(buf.toString());
+
+ TraceMethodVisitor tcv = createTraceMethodVisitor();
+ text.add(tcv.getText());
+
+ if (cv != null) {
+ tcv.mv = cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ return tcv;
+ }
+
+ public void visitEnd() {
+ text.add("}\n");
+
+ print(pw);
+ pw.flush();
+
+ if (cv != null) {
+ cv.visitEnd();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ protected TraceFieldVisitor createTraceFieldVisitor() {
+ return new TraceFieldVisitor();
+ }
+
+ protected TraceMethodVisitor createTraceMethodVisitor() {
+ return new TraceMethodVisitor();
+ }
+
+ /**
+ * Appends a string representation of the given access modifiers to {@link
+ * #buf buf}.
+ *
+ * @param access some access modifiers.
+ */
+ private void appendAccess(final int access) {
+ if ((access & Opcodes.ACC_PUBLIC) != 0) {
+ buf.append("public ");
+ }
+ if ((access & Opcodes.ACC_PRIVATE) != 0) {
+ buf.append("private ");
+ }
+ if ((access & Opcodes.ACC_PROTECTED) != 0) {
+ buf.append("protected ");
+ }
+ if ((access & Opcodes.ACC_FINAL) != 0) {
+ buf.append("final ");
+ }
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ buf.append("static ");
+ }
+ if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+ buf.append("synchronized ");
+ }
+ if ((access & Opcodes.ACC_VOLATILE) != 0) {
+ buf.append("volatile ");
+ }
+ if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+ buf.append("transient ");
+ }
+ if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+ buf.append("abstract ");
+ }
+ if ((access & Opcodes.ACC_STRICT) != 0) {
+ buf.append("strictfp ");
+ }
+ if ((access & Opcodes.ACC_ENUM) != 0) {
+ buf.append("enum ");
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceFieldVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceFieldVisitor.java
new file mode 100644
index 0000000..2642d2f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceFieldVisitor.java
@@ -0,0 +1,78 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+
+/**
+ * A {@link FieldVisitor} that prints a disassembled view of the fields it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class TraceFieldVisitor extends TraceAbstractVisitor implements
+ FieldVisitor
+{
+
+ /**
+ * The {@link FieldVisitor} to which this visitor delegates calls. May be
+ * <tt>null</tt>.
+ */
+ protected FieldVisitor fv;
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationVisitor av = super.visitAnnotation(desc, visible);
+ if (fv != null) {
+ ((TraceAnnotationVisitor) av).av = fv.visitAnnotation(desc, visible);
+ }
+ return av;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ super.visitAttribute(attr);
+
+ if (fv != null) {
+ fv.visitAttribute(attr);
+ }
+ }
+
+ public void visitEnd() {
+ super.visitEnd();
+
+ if (fv != null) {
+ fv.visitEnd();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceMethodVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceMethodVisitor.java
new file mode 100644
index 0000000..f545b9b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceMethodVisitor.java
@@ -0,0 +1,563 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.asm.signature.SignatureReader;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A {@link MethodVisitor} that prints a disassembled view of the methods it
+ * visits.
+ *
+ * @author Eric Bruneton
+ */
+public class TraceMethodVisitor extends TraceAbstractVisitor implements
+ MethodVisitor
+{
+
+ /**
+ * The label names. This map associate String values to Label keys.
+ */
+ protected final Map labelNames;
+ /**
+ * The {@link MethodVisitor} to which this visitor delegates calls. May be
+ * <tt>null</tt>.
+ */
+ protected MethodVisitor mv;
+ /**
+ * Tab for bytecode instructions.
+ */
+ protected String tab2 = " ";
+ /**
+ * Tab for table and lookup switch instructions.
+ */
+ protected String tab3 = " ";
+ /**
+ * Tab for labels.
+ */
+ protected String ltab = " ";
+
+ /**
+ * Constructs a new {@link TraceMethodVisitor}.
+ */
+ public TraceMethodVisitor() {
+ this(null);
+ }
+
+ /**
+ * Constructs a new {@link TraceMethodVisitor}.
+ *
+ * @param mv the {@link MethodVisitor} to which this visitor delegates
+ * calls. May be <tt>null</tt>.
+ */
+ public TraceMethodVisitor(final MethodVisitor mv) {
+ this.labelNames = new HashMap();
+ this.mv = mv;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor interface
+ // ------------------------------------------------------------------------
+
+ public AnnotationVisitor visitAnnotation(
+ final String desc,
+ final boolean visible)
+ {
+ AnnotationVisitor av = super.visitAnnotation(desc, visible);
+ if (mv != null) {
+ ((TraceAnnotationVisitor) av).av = mv.visitAnnotation(desc, visible);
+ }
+ return av;
+ }
+
+ public void visitAttribute(final Attribute attr) {
+ buf.setLength(0);
+ buf.append(tab).append("ATTRIBUTE ");
+ appendDescriptor(-1, attr.type);
+
+ if (attr instanceof Traceable) {
+ ((Traceable) attr).trace(buf, labelNames);
+ } else {
+ buf.append(" : unknown\n");
+ }
+
+ text.add(buf.toString());
+ if (mv != null) {
+ mv.visitAttribute(attr);
+ }
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ text.add(tab2 + "default=");
+ TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+ text.add(tav.getText());
+ text.add("\n");
+ if (mv != null) {
+ tav.av = mv.visitAnnotationDefault();
+ }
+ return tav;
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(
+ final int parameter,
+ final String desc,
+ final boolean visible)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append('@');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('(');
+ text.add(buf.toString());
+ TraceAnnotationVisitor tav = createTraceAnnotationVisitor();
+ text.add(tav.getText());
+ text.add(visible ? ") // parameter " : ") // invisible, parameter ");
+ text.add(new Integer(parameter));
+ text.add("\n");
+ if (mv != null) {
+ tav.av = mv.visitParameterAnnotation(parameter, desc, visible);
+ }
+ return tav;
+ }
+
+ public void visitCode() {
+ if (mv != null) {
+ mv.visitCode();
+ }
+ }
+
+ public void visitFrame(
+ final int type,
+ final int nLocal,
+ final Object[] local,
+ final int nStack,
+ final Object[] stack)
+ {
+ buf.setLength(0);
+ buf.append(ltab);
+ buf.append("FRAME ");
+ switch (type) {
+ case Opcodes.F_NEW:
+ case Opcodes.F_FULL:
+ buf.append("FULL [");
+ appendFrameTypes(nLocal, local);
+ buf.append("] [");
+ appendFrameTypes(nStack, stack);
+ buf.append(']');
+ break;
+ case Opcodes.F_APPEND:
+ buf.append("APPEND [");
+ appendFrameTypes(nLocal, local);
+ buf.append(']');
+ break;
+ case Opcodes.F_CHOP:
+ buf.append("CHOP ").append(nLocal);
+ break;
+ case Opcodes.F_SAME:
+ buf.append("SAME");
+ break;
+ case Opcodes.F_SAME1:
+ buf.append("SAME1 ");
+ appendFrameTypes(1, stack);
+ break;
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+ }
+
+ public void visitInsn(final int opcode) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ public void visitIntInsn(final int opcode, final int operand) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(opcode == Opcodes.NEWARRAY
+ ? TYPES[operand]
+ : Integer.toString(operand))
+ .append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append(OPCODES[opcode])
+ .append(' ')
+ .append(var)
+ .append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ public void visitTypeInsn(final int opcode, final String type) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ public void visitFieldInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(" : ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ public void visitMethodInsn(
+ final int opcode,
+ final String owner,
+ final String name,
+ final String desc)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendDescriptor(INTERNAL_NAME, owner);
+ buf.append('.').append(name).append(' ');
+ appendDescriptor(METHOD_DESCRIPTOR, desc);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ public void visitJumpInsn(final int opcode, final Label label) {
+ buf.setLength(0);
+ buf.append(tab2).append(OPCODES[opcode]).append(' ');
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ public void visitLabel(final Label label) {
+ buf.setLength(0);
+ buf.append(ltab);
+ appendLabel(label);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ }
+
+ public void visitLdcInsn(final Object cst) {
+ buf.setLength(0);
+ buf.append(tab2).append("LDC ");
+ if (cst instanceof String) {
+ AbstractVisitor.appendString(buf, (String) cst);
+ } else if (cst instanceof Type) {
+ buf.append(((Type) cst).getDescriptor()).append(".class");
+ } else {
+ buf.append(cst);
+ }
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ buf.setLength(0);
+ buf.append(tab2)
+ .append("IINC ")
+ .append(var)
+ .append(' ')
+ .append(increment)
+ .append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ public void visitTableSwitchInsn(
+ final int min,
+ final int max,
+ final Label dflt,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("TABLESWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(min + i).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ public void visitLookupSwitchInsn(
+ final Label dflt,
+ final int[] keys,
+ final Label[] labels)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("LOOKUPSWITCH\n");
+ for (int i = 0; i < labels.length; ++i) {
+ buf.append(tab3).append(keys[i]).append(": ");
+ appendLabel(labels[i]);
+ buf.append('\n');
+ }
+ buf.append(tab3).append("default: ");
+ appendLabel(dflt);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ buf.setLength(0);
+ buf.append(tab2).append("MULTIANEWARRAY ");
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ').append(dims).append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+
+ public void visitTryCatchBlock(
+ final Label start,
+ final Label end,
+ final Label handler,
+ final String type)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("TRYCATCHBLOCK ");
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ');
+ appendLabel(handler);
+ buf.append(' ');
+ appendDescriptor(INTERNAL_NAME, type);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ buf.setLength(0);
+ buf.append(tab2).append("LOCALVARIABLE ").append(name).append(' ');
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ buf.append(' ');
+ appendLabel(start);
+ buf.append(' ');
+ appendLabel(end);
+ buf.append(' ').append(index).append('\n');
+
+ if (signature != null) {
+ buf.append(tab2);
+ appendDescriptor(FIELD_SIGNATURE, signature);
+
+ TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+ SignatureReader r = new SignatureReader(signature);
+ r.acceptType(sv);
+ buf.append(tab2)
+ .append("// declaration: ")
+ .append(sv.getDeclaration())
+ .append('\n');
+ }
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+ }
+
+ public void visitLineNumber(final int line, final Label start) {
+ buf.setLength(0);
+ buf.append(tab2).append("LINENUMBER ").append(line).append(' ');
+ appendLabel(start);
+ buf.append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitLineNumber(line, start);
+ }
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ buf.setLength(0);
+ buf.append(tab2).append("MAXSTACK = ").append(maxStack).append('\n');
+ text.add(buf.toString());
+
+ buf.setLength(0);
+ buf.append(tab2).append("MAXLOCALS = ").append(maxLocals).append('\n');
+ text.add(buf.toString());
+
+ if (mv != null) {
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ public void visitEnd() {
+ super.visitEnd();
+
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ private void appendFrameTypes(final int n, final Object[] o) {
+ for (int i = 0; i < n; ++i) {
+ if (i > 0) {
+ buf.append(' ');
+ }
+ if (o[i] instanceof String) {
+ String desc = (String) o[i];
+ if (desc.startsWith("[")) {
+ appendDescriptor(FIELD_DESCRIPTOR, desc);
+ } else {
+ appendDescriptor(INTERNAL_NAME, desc);
+ }
+ } else if (o[i] instanceof Integer) {
+ switch (((Integer) o[i]).intValue()) {
+ case 0:
+ appendDescriptor(FIELD_DESCRIPTOR, "T");
+ break;
+ case 1:
+ appendDescriptor(FIELD_DESCRIPTOR, "I");
+ break;
+ case 2:
+ appendDescriptor(FIELD_DESCRIPTOR, "F");
+ break;
+ case 3:
+ appendDescriptor(FIELD_DESCRIPTOR, "D");
+ break;
+ case 4:
+ appendDescriptor(FIELD_DESCRIPTOR, "J");
+ break;
+ case 5:
+ appendDescriptor(FIELD_DESCRIPTOR, "N");
+ break;
+ case 6:
+ appendDescriptor(FIELD_DESCRIPTOR, "U");
+ break;
+ }
+ } else {
+ appendLabel((Label) o[i]);
+ }
+ }
+ }
+
+ /**
+ * Appends the name of the given label to {@link #buf buf}. Creates a new
+ * label name if the given label does not yet have one.
+ *
+ * @param l a label.
+ */
+ protected void appendLabel(final Label l) {
+ String name = (String) labelNames.get(l);
+ if (name == null) {
+ name = "L" + labelNames.size();
+ labelNames.put(l, name);
+ }
+ buf.append(name);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceSignatureVisitor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceSignatureVisitor.java
new file mode 100644
index 0000000..647a55b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/TraceSignatureVisitor.java
@@ -0,0 +1,300 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.signature.SignatureVisitor;
+
+/**
+ * A {@link SignatureVisitor} that prints a disassembled view of the signature
+ * it visits.
+ *
+ * @author Eugene Kuleshov
+ * @author Eric Bruneton
+ */
+public class TraceSignatureVisitor implements SignatureVisitor {
+
+ private final StringBuffer declaration;
+
+ private boolean isInterface;
+
+ private boolean seenFormalParameter;
+
+ private boolean seenInterfaceBound;
+
+ private boolean seenParameter;
+
+ private boolean seenInterface;
+
+ private StringBuffer returnType;
+
+ private StringBuffer exceptions;
+
+ /**
+ * Stack used to keep track of class types that have arguments. Each element
+ * of this stack is a boolean encoded in one bit. The top of the stack is
+ * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =
+ * /2.
+ */
+ private int argumentStack;
+
+ /**
+ * Stack used to keep track of array class types. Each element of this stack
+ * is a boolean encoded in one bit. The top of the stack is the lowest order
+ * bit. Pushing false = *2, pushing true = *2+1, popping = /2.
+ */
+ private int arrayStack;
+
+ private String separator = "";
+
+ public TraceSignatureVisitor(final int access) {
+ isInterface = (access & Opcodes.ACC_INTERFACE) != 0;
+ this.declaration = new StringBuffer();
+ }
+
+ private TraceSignatureVisitor(final StringBuffer buf) {
+ this.declaration = buf;
+ }
+
+ public void visitFormalTypeParameter(final String name) {
+ declaration.append(seenFormalParameter ? ", " : "<").append(name);
+ seenFormalParameter = true;
+ seenInterfaceBound = false;
+ }
+
+ public SignatureVisitor visitClassBound() {
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ public SignatureVisitor visitInterfaceBound() {
+ separator = seenInterfaceBound ? ", " : " extends ";
+ seenInterfaceBound = true;
+ startType();
+ return this;
+ }
+
+ public SignatureVisitor visitSuperclass() {
+ endFormals();
+ separator = " extends ";
+ startType();
+ return this;
+ }
+
+ public SignatureVisitor visitInterface() {
+ separator = seenInterface ? ", " : isInterface
+ ? " extends "
+ : " implements ";
+ seenInterface = true;
+ startType();
+ return this;
+ }
+
+ public SignatureVisitor visitParameterType() {
+ endFormals();
+ if (seenParameter) {
+ declaration.append(", ");
+ } else {
+ seenParameter = true;
+ declaration.append('(');
+ }
+ startType();
+ return this;
+ }
+
+ public SignatureVisitor visitReturnType() {
+ endFormals();
+ if (seenParameter) {
+ seenParameter = false;
+ } else {
+ declaration.append('(');
+ }
+ declaration.append(')');
+ returnType = new StringBuffer();
+ return new TraceSignatureVisitor(returnType);
+ }
+
+ public SignatureVisitor visitExceptionType() {
+ if (exceptions == null) {
+ exceptions = new StringBuffer();
+ } else {
+ exceptions.append(", ");
+ }
+ // startType();
+ return new TraceSignatureVisitor(exceptions);
+ }
+
+ public void visitBaseType(final char descriptor) {
+ switch (descriptor) {
+ case 'V':
+ declaration.append("void");
+ break;
+ case 'B':
+ declaration.append("byte");
+ break;
+ case 'J':
+ declaration.append("long");
+ break;
+ case 'Z':
+ declaration.append("boolean");
+ break;
+ case 'I':
+ declaration.append("int");
+ break;
+ case 'S':
+ declaration.append("short");
+ break;
+ case 'C':
+ declaration.append("char");
+ break;
+ case 'F':
+ declaration.append("float");
+ break;
+ // case 'D':
+ default:
+ declaration.append("double");
+ break;
+ }
+ endType();
+ }
+
+ public void visitTypeVariable(final String name) {
+ declaration.append(name);
+ endType();
+ }
+
+ public SignatureVisitor visitArrayType() {
+ startType();
+ arrayStack |= 1;
+ return this;
+ }
+
+ public void visitClassType(final String name) {
+ if ("java/lang/Object".equals(name)) {
+ // Map<java.lang.Object,java.util.List>
+ // or
+ // abstract public V get(Object key); (seen in Dictionary.class)
+ // should have Object
+ // but java.lang.String extends java.lang.Object is unnecessary
+ boolean needObjectClass = argumentStack % 2 != 0 || seenParameter;
+ if (needObjectClass) {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ } else {
+ declaration.append(separator).append(name.replace('/', '.'));
+ }
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ public void visitInnerClassType(final String name) {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ declaration.append('.');
+ declaration.append(separator).append(name.replace('/', '.'));
+ separator = "";
+ argumentStack *= 2;
+ }
+
+ public void visitTypeArgument() {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+ declaration.append('?');
+ }
+
+ public SignatureVisitor visitTypeArgument(final char tag) {
+ if (argumentStack % 2 == 0) {
+ ++argumentStack;
+ declaration.append('<');
+ } else {
+ declaration.append(", ");
+ }
+
+ if (tag == EXTENDS) {
+ declaration.append("? extends ");
+ } else if (tag == SUPER) {
+ declaration.append("? super ");
+ }
+
+ startType();
+ return this;
+ }
+
+ public void visitEnd() {
+ if (argumentStack % 2 != 0) {
+ declaration.append('>');
+ }
+ argumentStack /= 2;
+ endType();
+ }
+
+ public String getDeclaration() {
+ return declaration.toString();
+ }
+
+ public String getReturnType() {
+ return returnType == null ? null : returnType.toString();
+ }
+
+ public String getExceptions() {
+ return exceptions == null ? null : exceptions.toString();
+ }
+
+ // -----------------------------------------------
+
+ private void endFormals() {
+ if (seenFormalParameter) {
+ declaration.append('>');
+ seenFormalParameter = false;
+ }
+ }
+
+ private void startType() {
+ arrayStack *= 2;
+ }
+
+ private void endType() {
+ if (arrayStack % 2 == 0) {
+ arrayStack /= 2;
+ } else {
+ while (arrayStack % 2 != 0) {
+ arrayStack /= 2;
+ declaration.append("[]");
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/Traceable.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/Traceable.java
new file mode 100644
index 0000000..610439b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/Traceable.java
@@ -0,0 +1,52 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.api.mockito.repackaged.asm.util;
+
+import java.util.Map;
+
+/**
+ * An attribute that can print eadable representation of the attribute.
+ *
+ * Implementation should construct readable output from an attribute data
+ * structures for current attribute state. Such representation could be used in
+ * unit test assertions.
+ *
+ * @author Eugene Kuleshov
+ */
+public interface Traceable {
+
+ /**
+ * Build a human readable representation of the attribute.
+ *
+ * @param buf A buffer used for printing Java code.
+ * @param labelNames map of label instances to their names.
+ */
+ void trace(StringBuffer buf, Map labelNames);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/package.html
new file mode 100644
index 0000000..f399069
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/asm/util/package.html
@@ -0,0 +1,70 @@
+<!--
+ ~ ASM: a very small and fast Java bytecode manipulation framework
+ ~ Copyright (c) 2000-2007 INRIA, France Telecom
+ ~ All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without
+ ~ modification, are permitted provided that the following conditions
+ ~ are met:
+ ~ 1. Redistributions of source code must retain the above copyright
+ ~ notice, this list of conditions and the following disclaimer.
+ ~ 2. Redistributions in binary form must reproduce the above copyright
+ ~ notice, this list of conditions and the following disclaimer in the
+ ~ documentation and/or other materials provided with the distribution.
+ ~ 3. Neither the name of the copyright holders nor the names of its
+ ~ contributors may be used to endorse or promote products derived from
+ ~ this software without specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ ~ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ ~ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ~ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ ~ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ ~ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ ~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ ~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ ~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ ~ THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+
+<html>
+<!--
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2005 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<body>
+Provides ASM visitors that can be useful for programming and
+debugging purposes. These class visitors are normally not used by applications
+at runtime. This is why they are bundled in an optional <tt>asm-util.jar</tt>
+library that is separated from (but requires) the <tt>asm.jar</tt> library,
+which contains the core ASM framework.
+
+ at since ASM 1.3.2
+</body>
+</html>
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanCopier.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanCopier.java
new file mode 100644
index 0000000..8b6ce4a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanCopier.java
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.Converter;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Chris Nokleberg
+ */
+abstract public class BeanCopier
+{
+ private static final BeanCopierKey KEY_FACTORY =
+ (BeanCopierKey) KeyFactory.create(BeanCopierKey.class);
+ private static final Type CONVERTER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.core.Converter");
+ private static final Type BEAN_COPIER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.beans.BeanCopier");
+ private static final Signature COPY =
+ new Signature("copy", Type.VOID_TYPE, new Type[]{ Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER });
+ private static final Signature CONVERT =
+ TypeUtils.parseSignature("Object convert(Object, Class, Object)");
+
+ public static BeanCopier create(Class source, Class target, boolean useConverter) {
+ Generator gen = new Generator();
+ gen.setSource(source);
+ gen.setTarget(target);
+ gen.setUseConverter(useConverter);
+ return gen.create();
+ }
+
+ abstract public void copy(Object from, Object to, Converter converter);
+
+ interface BeanCopierKey {
+ public Object newInstance(String source, String target, boolean useConverter);
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(BeanCopier.class.getName());
+ private Class source;
+ private Class target;
+ private boolean useConverter;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) {
+ // TODO: allow automatic widening conversions?
+ return setter.getPropertyType().isAssignableFrom(getter.getPropertyType());
+ }
+
+ public void setSource(Class source) {
+ if(!Modifier.isPublic(source.getModifiers())){
+ setNamePrefix(source.getName());
+ }
+ this.source = source;
+ }
+
+ public void setTarget(Class target) {
+ if(!Modifier.isPublic(target.getModifiers())){
+ setNamePrefix(target.getName());
+ }
+
+ this.target = target;
+ }
+
+ public void setUseConverter(boolean useConverter) {
+ this.useConverter = useConverter;
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return source.getClassLoader();
+ }
+
+ public BeanCopier create() {
+ Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter);
+ return (BeanCopier)super.create(key);
+ }
+
+ public void generateClass(ClassVisitor v) {
+ Type sourceType = Type.getType(source);
+ Type targetType = Type.getType(target);
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ BEAN_COPIER,
+ null,
+ Constants.SOURCE_FILE);
+
+ EmitUtils.null_constructor(ce);
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null);
+ PropertyDescriptor[] getters = ReflectUtils.getBeanGetters(source);
+ PropertyDescriptor[] setters = ReflectUtils.getBeanGetters(target);
+
+ Map names = new HashMap();
+ for (int i = 0; i < getters.length; i++) {
+ names.put(getters[i].getName(), getters[i]);
+ }
+ Local targetLocal = e.make_local();
+ Local sourceLocal = e.make_local();
+ if (useConverter) {
+ e.load_arg(1);
+ e.checkcast(targetType);
+ e.store_local(targetLocal);
+ e.load_arg(0);
+ e.checkcast(sourceType);
+ e.store_local(sourceLocal);
+ } else {
+ e.load_arg(1);
+ e.checkcast(targetType);
+ e.load_arg(0);
+ e.checkcast(sourceType);
+ }
+ for (int i = 0; i < setters.length; i++) {
+ PropertyDescriptor setter = setters[i];
+ PropertyDescriptor getter = (PropertyDescriptor)names.get(setter.getName());
+ if (getter != null) {
+ MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
+ MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod());
+ if (useConverter) {
+ Type setterType = write.getSignature().getArgumentTypes()[0];
+ e.load_local(targetLocal);
+ e.load_arg(2);
+ e.load_local(sourceLocal);
+ e.invoke(read);
+ e.box(read.getSignature().getReturnType());
+ EmitUtils.load_class(e, setterType);
+ e.push(write.getSignature().getName());
+ e.invoke_interface(CONVERTER, CONVERT);
+ e.unbox_or_zero(setterType);
+ e.invoke(write);
+ } else if (compatible(getter, setter)) {
+ e.dup2();
+ e.invoke(read);
+ e.invoke(write);
+ }
+ }
+ }
+ e.return_value();
+ e.end_method();
+ ce.end_class();
+ }
+
+ protected Object firstInstance(Class type) {
+ return ReflectUtils.newInstance(type);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanGenerator.java
new file mode 100644
index 0000000..885baae
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanGenerator.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * @author Juozas Baliuka, Chris Nokleberg
+ */
+public class BeanGenerator extends AbstractClassGenerator
+{
+ private static final Source SOURCE = new Source(BeanGenerator.class.getName());
+ private static final BeanGeneratorKey KEY_FACTORY =
+ (BeanGeneratorKey) KeyFactory.create(BeanGeneratorKey.class);
+ private Class superclass;
+ private Map props = new HashMap();
+ private boolean classOnly;
+ public BeanGenerator() {
+ super(SOURCE);
+ }
+
+ public static void addProperties(BeanGenerator gen, Map props) {
+ for (Iterator it = props.keySet().iterator(); it.hasNext();) {
+ String name = (String)it.next();
+ gen.addProperty(name, (Class)props.get(name));
+ }
+ }
+
+ public static void addProperties(BeanGenerator gen, Class type) {
+ addProperties(gen, ReflectUtils.getBeanProperties(type));
+ }
+
+ public static void addProperties(BeanGenerator gen, PropertyDescriptor[] descriptors) {
+ for (int i = 0; i < descriptors.length; i++) {
+ gen.addProperty(descriptors[i].getName(), descriptors[i].getPropertyType());
+ }
+ }
+
+ /**
+ * Set the class which the generated class will extend. The class
+ * must not be declared as final, and must have a non-private
+ * no-argument constructor.
+ * @param superclass class to extend, or null to extend Object
+ */
+ public void setSuperclass(Class superclass) {
+ if (superclass != null && superclass.equals(Object.class)) {
+ superclass = null;
+ }
+ this.superclass = superclass;
+ }
+
+ public void addProperty(String name, Class type) {
+ if (props.containsKey(name)) {
+ throw new IllegalArgumentException("Duplicate property name \"" + name + "\"");
+ }
+ props.put(name, Type.getType(type));
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ if (superclass != null) {
+ return superclass.getClassLoader();
+ } else {
+ return null;
+ }
+ }
+
+ public Object create() {
+ classOnly = false;
+ return createHelper();
+ }
+
+ public Object createClass() {
+ classOnly = true;
+ return createHelper();
+ }
+
+ private Object createHelper() {
+ if (superclass != null) {
+ setNamePrefix(superclass.getName());
+ }
+ String superName = (superclass != null) ? superclass.getName() : "java.lang.Object";
+ Object key = KEY_FACTORY.newInstance(superName, props);
+ return super.create(key);
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ int size = props.size();
+ String[] names = (String[])props.keySet().toArray(new String[size]);
+ Type[] types = new Type[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = (Type)props.get(names[i]);
+ }
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ superclass != null ? Type.getType(superclass) : Constants.TYPE_OBJECT,
+ null,
+ null);
+ EmitUtils.null_constructor(ce);
+ EmitUtils.add_properties(ce, names, types);
+ ce.end_class();
+ }
+
+ protected Object firstInstance(Class type) {
+ if (classOnly) {
+ return type;
+ } else {
+ return ReflectUtils.newInstance(type);
+ }
+ }
+
+ protected Object nextInstance(Object instance) {
+ Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass();
+ if (classOnly) {
+ return protoclass;
+ } else {
+ return ReflectUtils.newInstance(protoclass);
+ }
+ }
+
+ interface BeanGeneratorKey {
+ public Object newInstance(String superclass, Map props);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMap.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMap.java
new file mode 100644
index 0000000..07e7aa8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMap.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A <code>Map</code>-based view of a JavaBean. The default set of keys is the
+ * union of all property names (getters or setters). An attempt to set
+ * a read-only property will be ignored, and write-only properties will
+ * be returned as <code>null</code>. Removal of objects is not a
+ * supported (the key set is fixed).
+ * @author Chris Nokleberg
+ */
+abstract public class BeanMap implements Map {
+ /**
+ * Limit the properties reflected in the key set of the map
+ * to readable properties.
+ * @see BeanMap.Generator#setRequire
+ */
+ public static final int REQUIRE_GETTER = 1;
+
+ /**
+ * Limit the properties reflected in the key set of the map
+ * to writable properties.
+ * @see BeanMap.Generator#setRequire
+ */
+ public static final int REQUIRE_SETTER = 2;
+
+ /**
+ * Helper method to create a new <code>BeanMap</code>. For finer
+ * control over the generated instance, use a new instance of
+ * <code>BeanMap.Generator</code> instead of this static method.
+ * @param bean the JavaBean underlying the map
+ * @return a new <code>BeanMap</code> instance
+ */
+ public static BeanMap create(Object bean) {
+ Generator gen = new Generator();
+ gen.setBean(bean);
+ return gen.create();
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(BeanMap.class.getName());
+
+ private static final BeanMapKey KEY_FACTORY =
+ (BeanMapKey) KeyFactory.create(BeanMapKey.class, KeyFactory.CLASS_BY_NAME);
+
+ interface BeanMapKey {
+ public Object newInstance(Class type, int require);
+ }
+
+ private Object bean;
+ private Class beanClass;
+ private int require;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ /**
+ * Set the bean that the generated map should reflect. The bean may be swapped
+ * out for another bean of the same type using {@link #setBean}.
+ * Calling this method overrides any value previously set using {@link #setBeanClass}.
+ * You must call either this method or {@link #setBeanClass} before {@link #create}.
+ * @param bean the initial bean
+ */
+ public void setBean(Object bean) {
+ this.bean = bean;
+ if (bean != null)
+ beanClass = bean.getClass();
+ }
+
+ /**
+ * Set the class of the bean that the generated map should support.
+ * You must call either this method or {@link #setBeanClass} before {@link #create}.
+ * @param beanClass the class of the bean
+ */
+ public void setBeanClass(Class beanClass) {
+ this.beanClass = beanClass;
+ }
+
+ /**
+ * Limit the properties reflected by the generated map.
+ * @param require any combination of {@link #REQUIRE_GETTER} and
+ * {@link #REQUIRE_SETTER}; default is zero (any property allowed)
+ */
+ public void setRequire(int require) {
+ this.require = require;
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return beanClass.getClassLoader();
+ }
+
+ /**
+ * Create a new instance of the <code>BeanMap</code>. An existing
+ * generated class will be reused if possible.
+ */
+ public BeanMap create() {
+ if (beanClass == null)
+ throw new IllegalArgumentException("Class of bean unknown");
+ setNamePrefix(beanClass.getName());
+ return (BeanMap)super.create(KEY_FACTORY.newInstance(beanClass, require));
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ new BeanMapEmitter(v, getClassName(), beanClass, require);
+ }
+
+ protected Object firstInstance(Class type) {
+ return ((BeanMap) ReflectUtils.newInstance(type)).newInstance(bean);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return ((BeanMap)instance).newInstance(bean);
+ }
+ }
+
+ /**
+ * Create a new <code>BeanMap</code> instance using the specified bean.
+ * This is faster than using the {@link #create} static method.
+ * @param bean the JavaBean underlying the map
+ * @return a new <code>BeanMap</code> instance
+ */
+ abstract public BeanMap newInstance(Object bean);
+
+ /**
+ * Get the type of a property.
+ * @param name the name of the JavaBean property
+ * @return the type of the property, or null if the property does not exist
+ */
+ abstract public Class getPropertyType(String name);
+
+ protected Object bean;
+
+ protected BeanMap() {
+ }
+
+ protected BeanMap(Object bean) {
+ setBean(bean);
+ }
+
+ public Object get(Object key) {
+ return get(bean, key);
+ }
+
+ public Object put(Object key, Object value) {
+ return put(bean, key, value);
+ }
+
+ /**
+ * Get the property of a bean. This allows a <code>BeanMap</code>
+ * to be used statically for multiple beans--the bean instance tied to the
+ * map is ignored and the bean passed to this method is used instead.
+ * @param bean the bean to query; must be compatible with the type of
+ * this <code>BeanMap</code>
+ * @param key must be a String
+ * @return the current value, or null if there is no matching property
+ */
+ abstract public Object get(Object bean, Object key);
+
+ /**
+ * Set the property of a bean. This allows a <code>BeanMap</code>
+ * to be used statically for multiple beans--the bean instance tied to the
+ * map is ignored and the bean passed to this method is used instead.
+ * @param key must be a String
+ * @return the old value, if there was one, or null
+ */
+ abstract public Object put(Object bean, Object key, Object value);
+
+ /**
+ * Change the underlying bean this map should use.
+ * @param bean the new JavaBean
+ * @see #getBean
+ */
+ public void setBean(Object bean) {
+ this.bean = bean;
+ }
+
+ /**
+ * Return the bean currently in use by this map.
+ * @return the current JavaBean
+ * @see #setBean
+ */
+ public Object getBean() {
+ return bean;
+ }
+
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ public boolean containsKey(Object key) {
+ return keySet().contains(key);
+ }
+
+ public boolean containsValue(Object value) {
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ Object v = get(it.next());
+ if (((value == null) && (v == null)) || value.equals(v))
+ return true;
+ }
+ return false;
+ }
+
+ public int size() {
+ return keySet().size();
+ }
+
+ public boolean isEmpty() {
+ return size() == 0;
+ }
+
+ public Object remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ public void putAll(Map t) {
+ for (Iterator it = t.keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ put(key, t.get(key));
+ }
+ }
+
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof Map)) {
+ return false;
+ }
+ Map other = (Map)o;
+ if (size() != other.size()) {
+ return false;
+ }
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ if (!other.containsKey(key)) {
+ return false;
+ }
+ Object v1 = get(key);
+ Object v2 = other.get(key);
+ if (!((v1 == null) ? v2 == null : v1.equals(v2))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public int hashCode() {
+ int code = 0;
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ Object value = get(key);
+ code += ((key == null) ? 0 : key.hashCode()) ^
+ ((value == null) ? 0 : value.hashCode());
+ }
+ return code;
+ }
+
+ // TODO: optimize
+ public Set entrySet() {
+ HashMap copy = new HashMap();
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ copy.put(key, get(key));
+ }
+ return Collections.unmodifiableMap(copy).entrySet();
+ }
+
+ public Collection values() {
+ Set keys = keySet();
+ List values = new ArrayList(keys.size());
+ for (Iterator it = keys.iterator(); it.hasNext();) {
+ values.add(get(it.next()));
+ }
+ return Collections.unmodifiableCollection(values);
+ }
+
+ /*
+ * @see java.util.AbstractMap#toString
+ */
+ public String toString()
+ {
+ StringBuffer sb = new StringBuffer();
+ sb.append('{');
+ for (Iterator it = keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ sb.append(key);
+ sb.append('=');
+ sb.append(get(key));
+ if (it.hasNext()) {
+ sb.append(", ");
+ }
+ }
+ sb.append('}');
+ return sb.toString();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMapEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMapEmitter.java
new file mode 100644
index 0000000..54b8815
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BeanMapEmitter.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+class BeanMapEmitter extends ClassEmitter {
+ private static final Type BEAN_MAP =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.beans.BeanMap");
+ private static final Type FIXED_KEY_SET =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.beans.FixedKeySet");
+ private static final Signature CSTRUCT_OBJECT =
+ TypeUtils.parseConstructor("Object");
+ private static final Signature CSTRUCT_STRING_ARRAY =
+ TypeUtils.parseConstructor("String[]");
+ private static final Signature BEAN_MAP_GET =
+ TypeUtils.parseSignature("Object get(Object, Object)");
+ private static final Signature BEAN_MAP_PUT =
+ TypeUtils.parseSignature("Object put(Object, Object, Object)");
+ private static final Signature KEY_SET =
+ TypeUtils.parseSignature("java.util.Set keySet()");
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", BEAN_MAP, new Type[]{ Constants.TYPE_OBJECT });
+ private static final Signature GET_PROPERTY_TYPE =
+ TypeUtils.parseSignature("Class getPropertyType(String)");
+
+ public BeanMapEmitter(ClassVisitor v, String className, Class type, int require) {
+ super(v);
+
+ begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(this);
+ EmitUtils.factory_method(this, NEW_INSTANCE);
+ generateConstructor();
+
+ Map getters = makePropertyMap(ReflectUtils.getBeanGetters(type));
+ Map setters = makePropertyMap(ReflectUtils.getBeanSetters(type));
+ Map allProps = new HashMap();
+ allProps.putAll(getters);
+ allProps.putAll(setters);
+
+ if (require != 0) {
+ for (Iterator it = allProps.keySet().iterator(); it.hasNext();) {
+ String name = (String)it.next();
+ if ((((require & BeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) ||
+ (((require & BeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) {
+ it.remove();
+ getters.remove(name);
+ setters.remove(name);
+ }
+ }
+ }
+ generateGet(type, getters);
+ generatePut(type, setters);
+
+ String[] allNames = getNames(allProps);
+ generateKeySet(allNames);
+ generateGetPropertyType(allProps, allNames);
+ end_class();
+ }
+
+ private Map makePropertyMap(PropertyDescriptor[] props) {
+ Map names = new HashMap();
+ for (int i = 0; i < props.length; i++) {
+ names.put(((PropertyDescriptor)props[i]).getName(), props[i]);
+ }
+ return names;
+ }
+
+ private String[] getNames(Map propertyMap) {
+ return (String[])propertyMap.keySet().toArray(new String[propertyMap.size()]);
+ }
+
+ private void generateConstructor() {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
+ e.load_this();
+ e.load_arg(0);
+ e.super_invoke_constructor(CSTRUCT_OBJECT);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void generateGet(Class type, final Map getters) {
+ final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null);
+ e.load_arg(0);
+ e.checkcast(Type.getType(type));
+ e.load_arg(1);
+ e.checkcast(Constants.TYPE_STRING);
+ EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ PropertyDescriptor pd = (PropertyDescriptor)getters.get(key);
+ MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod());
+ e.invoke(method);
+ e.box(method.getSignature().getReturnType());
+ e.return_value();
+ }
+ public void processDefault() {
+ e.aconst_null();
+ e.return_value();
+ }
+ });
+ e.end_method();
+ }
+
+ private void generatePut(Class type, final Map setters) {
+ final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null);
+ e.load_arg(0);
+ e.checkcast(Type.getType(type));
+ e.load_arg(1);
+ e.checkcast(Constants.TYPE_STRING);
+ EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ PropertyDescriptor pd = (PropertyDescriptor)setters.get(key);
+ if (pd.getReadMethod() == null) {
+ e.aconst_null();
+ } else {
+ MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod());
+ e.dup();
+ e.invoke(read);
+ e.box(read.getSignature().getReturnType());
+ }
+ e.swap(); // move old value behind bean
+ e.load_arg(2); // new value
+ MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod());
+ e.unbox(write.getSignature().getArgumentTypes()[0]);
+ e.invoke(write);
+ e.return_value();
+ }
+ public void processDefault() {
+ // fall-through
+ }
+ });
+ e.aconst_null();
+ e.return_value();
+ e.end_method();
+ }
+
+ private void generateKeySet(String[] allNames) {
+ // static initializer
+ declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null);
+
+ CodeEmitter e = begin_static();
+ e.new_instance(FIXED_KEY_SET);
+ e.dup();
+ EmitUtils.push_array(e, allNames);
+ e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY);
+ e.putfield("keys");
+ e.return_value();
+ e.end_method();
+
+ // keySet
+ e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null);
+ e.load_this();
+ e.getfield("keys");
+ e.return_value();
+ e.end_method();
+ }
+
+ private void generateGetPropertyType(final Map allProps, String[] allNames) {
+ final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null);
+ e.load_arg(0);
+ EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ PropertyDescriptor pd = (PropertyDescriptor)allProps.get(key);
+ EmitUtils.load_class(e, Type.getType(pd.getPropertyType()));
+ e.return_value();
+ }
+ public void processDefault() {
+ e.aconst_null();
+ e.return_value();
+ }
+ });
+ e.end_method();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBean.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBean.java
new file mode 100644
index 0000000..402434b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBean.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+/**
+ * @author Juozas Baliuka
+ */
+abstract public class BulkBean
+{
+ private static final BulkBeanKey KEY_FACTORY =
+ (BulkBeanKey) KeyFactory.create(BulkBeanKey.class);
+ protected Class target;
+ protected String[] getters, setters;
+ protected Class[] types;
+ protected BulkBean() { }
+
+ public static BulkBean create(Class target, String[] getters, String[] setters, Class[] types) {
+ Generator gen = new Generator();
+ gen.setTarget(target);
+ gen.setGetters(getters);
+ gen.setSetters(setters);
+ gen.setTypes(types);
+ return gen.create();
+ }
+
+ abstract public void getPropertyValues(Object bean, Object[] values);
+ abstract public void setPropertyValues(Object bean, Object[] values);
+
+ public Object[] getPropertyValues(Object bean) {
+ Object[] values = new Object[getters.length];
+ getPropertyValues(bean, values);
+ return values;
+ }
+
+ public Class[] getPropertyTypes() {
+ return (Class[])types.clone();
+ }
+
+ public String[] getGetters() {
+ return (String[])getters.clone();
+ }
+
+ public String[] getSetters() {
+ return (String[])setters.clone();
+ }
+
+ interface BulkBeanKey {
+ public Object newInstance(String target, String[] getters, String[] setters, String[] types);
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(BulkBean.class.getName());
+ private Class target;
+ private String[] getters;
+ private String[] setters;
+ private Class[] types;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ public void setTarget(Class target) {
+ this.target = target;
+ }
+
+ public void setGetters(String[] getters) {
+ this.getters = getters;
+ }
+
+ public void setSetters(String[] setters) {
+ this.setters = setters;
+ }
+
+ public void setTypes(Class[] types) {
+ this.types = types;
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return target.getClassLoader();
+ }
+
+ public BulkBean create() {
+ setNamePrefix(target.getName());
+ String targetClassName = target.getName();
+ String[] typeClassNames = ReflectUtils.getNames(types);
+ Object key = KEY_FACTORY.newInstance(targetClassName, getters, setters, typeClassNames);
+ return (BulkBean)super.create(key);
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ new BulkBeanEmitter(v, getClassName(), target, getters, setters, types);
+ }
+
+ protected Object firstInstance(Class type) {
+ BulkBean instance = (BulkBean)ReflectUtils.newInstance(type);
+ instance.target = target;
+
+ int length = getters.length;
+ instance.getters = new String[length];
+ System.arraycopy(getters, 0, instance.getters, 0, length);
+
+ instance.setters = new String[length];
+ System.arraycopy(setters, 0, instance.setters, 0, length);
+
+ instance.types = new Class[types.length];
+ System.arraycopy(types, 0, instance.types, 0, types.length);
+
+ return instance;
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanEmitter.java
new file mode 100644
index 0000000..b9a691d
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanEmitter.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.Block;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+class BulkBeanEmitter extends ClassEmitter {
+ private static final Signature GET_PROPERTY_VALUES =
+ TypeUtils.parseSignature("void getPropertyValues(Object, Object[])");
+ private static final Signature SET_PROPERTY_VALUES =
+ TypeUtils.parseSignature("void setPropertyValues(Object, Object[])");
+ private static final Signature CSTRUCT_EXCEPTION =
+ TypeUtils.parseConstructor("Throwable, int");
+ private static final Type BULK_BEAN =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.beans.BulkBean");
+ private static final Type BULK_BEAN_EXCEPTION =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.beans.BulkBeanException");
+
+ public BulkBeanEmitter(ClassVisitor v,
+ String className,
+ Class target,
+ String[] getterNames,
+ String[] setterNames,
+ Class[] types) {
+ super(v);
+
+ Method[] getters = new Method[getterNames.length];
+ Method[] setters = new Method[setterNames.length];
+ validate(target, getterNames, setterNames, types, getters, setters);
+
+ begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BULK_BEAN, null, Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(this);
+ generateGet(target, getters);
+ generateSet(target, setters);
+ end_class();
+ }
+
+ private static void validate(Class target,
+ String[] getters,
+ String[] setters,
+ Class[] types,
+ Method[] getters_out,
+ Method[] setters_out) {
+ int i = -1;
+ if (setters.length != types.length || getters.length != types.length) {
+ throw new BulkBeanException("accessor array length must be equal type array length", i);
+ }
+ try {
+ for (i = 0; i < types.length; i++) {
+ if (getters[i] != null) {
+ Method method = ReflectUtils.findDeclaredMethod(target, getters[i], null);
+ if (method.getReturnType() != types[i]) {
+ throw new BulkBeanException("Specified type " + types[i] +
+ " does not match declared type " + method.getReturnType(), i);
+ }
+ if (Modifier.isPrivate(method.getModifiers())) {
+ throw new BulkBeanException("Property is private", i);
+ }
+ getters_out[i] = method;
+ }
+ if (setters[i] != null) {
+ Method method = ReflectUtils.findDeclaredMethod(target, setters[i], new Class[]{ types[i] });
+ if (Modifier.isPrivate(method.getModifiers()) ){
+ throw new BulkBeanException("Property is private", i);
+ }
+ setters_out[i] = method;
+ }
+ }
+ } catch (NoSuchMethodException e) {
+ throw new BulkBeanException("Cannot find specified property", i);
+ }
+ }
+
+ private void generateGet(final Class target, final Method[] getters) {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_VALUES, null);
+ if (getters.length >= 0) {
+ e.load_arg(0);
+ e.checkcast(Type.getType(target));
+ Local bean = e.make_local();
+ e.store_local(bean);
+ for (int i = 0; i < getters.length; i++) {
+ if (getters[i] != null) {
+ MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
+ e.load_arg(1);
+ e.push(i);
+ e.load_local(bean);
+ e.invoke(getter);
+ e.box(getter.getSignature().getReturnType());
+ e.aastore();
+ }
+ }
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ private void generateSet(final Class target, final Method[] setters) {
+ // setPropertyValues
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SET_PROPERTY_VALUES, null);
+ if (setters.length > 0) {
+ Local index = e.make_local(Type.INT_TYPE);
+ e.push(0);
+ e.store_local(index);
+ e.load_arg(0);
+ e.checkcast(Type.getType(target));
+ e.load_arg(1);
+ Block handler = e.begin_block();
+ int lastIndex = 0;
+ for (int i = 0; i < setters.length; i++) {
+ if (setters[i] != null) {
+ MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
+ int diff = i - lastIndex;
+ if (diff > 0) {
+ e.iinc(index, diff);
+ lastIndex = i;
+ }
+ e.dup2();
+ e.aaload(i);
+ e.unbox(setter.getSignature().getArgumentTypes()[0]);
+ e.invoke(setter);
+ }
+ }
+ handler.end();
+ e.return_value();
+ e.catch_exception(handler, Constants.TYPE_THROWABLE);
+ e.new_instance(BULK_BEAN_EXCEPTION);
+ e.dup_x1();
+ e.swap();
+ e.load_local(index);
+ e.invoke_constructor(BULK_BEAN_EXCEPTION, CSTRUCT_EXCEPTION);
+ e.athrow();
+ } else {
+ e.return_value();
+ }
+ e.end_method();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanException.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanException.java
new file mode 100644
index 0000000..1f2f142
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/BulkBeanException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+public class BulkBeanException extends RuntimeException
+{
+ private int index;
+ private Throwable cause;
+
+ public BulkBeanException(String message, int index) {
+ super(message);
+ this.index = index;
+ }
+
+ public BulkBeanException(Throwable cause, int index) {
+ super(cause.getMessage());
+ this.index = index;
+ this.cause = cause;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/FixedKeySet.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/FixedKeySet.java
new file mode 100644
index 0000000..80bcb1e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/FixedKeySet.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import java.util.AbstractSet;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public /* need it for class loading */ class FixedKeySet extends AbstractSet {
+ private Set set;
+ private int size;
+
+ public FixedKeySet(String[] keys) {
+ size = keys.length;
+ set = Collections.unmodifiableSet(new HashSet(Arrays.asList(keys)));
+ }
+
+ public Iterator iterator() {
+ return set.iterator();
+ }
+
+ public int size() {
+ return size;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/ImmutableBean.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/ImmutableBean.java
new file mode 100644
index 0000000..277dc61
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/beans/ImmutableBean.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.beans;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+
+/**
+ * @author Chris Nokleberg
+ */
+public class ImmutableBean
+{
+ private static final Type ILLEGAL_STATE_EXCEPTION =
+ TypeUtils.parseType("IllegalStateException");
+ private static final Signature CSTRUCT_OBJECT =
+ TypeUtils.parseConstructor("Object");
+ private static final Class[] OBJECT_CLASSES = { Object.class };
+ private static final String FIELD_NAME = "CGLIB$RWBean";
+
+ private ImmutableBean() {
+ }
+
+ public static Object create(Object bean) {
+ Generator gen = new Generator();
+ gen.setBean(bean);
+ return gen.create();
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(ImmutableBean.class.getName());
+ private Object bean;
+ private Class target;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ public void setBean(Object bean) {
+ this.bean = bean;
+ target = bean.getClass();
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return target.getClassLoader();
+ }
+
+ public Object create() {
+ String name = target.getName();
+ setNamePrefix(name);
+ return super.create(name);
+ }
+
+ public void generateClass(ClassVisitor v) {
+ Type targetType = Type.getType(target);
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ targetType,
+ null,
+ Constants.SOURCE_FILE);
+
+ ce.declare_field(Constants.ACC_FINAL | Constants.ACC_PRIVATE, FIELD_NAME, targetType, null);
+
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
+ e.load_this();
+ e.super_invoke_constructor();
+ e.load_this();
+ e.load_arg(0);
+ e.checkcast(targetType);
+ e.putfield(FIELD_NAME);
+ e.return_value();
+ e.end_method();
+
+ PropertyDescriptor[] descriptors = ReflectUtils.getBeanProperties(target);
+ Method[] getters = ReflectUtils.getPropertyMethods(descriptors, true, false);
+ Method[] setters = ReflectUtils.getPropertyMethods(descriptors, false, true);
+
+ for (int i = 0; i < getters.length; i++) {
+ MethodInfo getter = ReflectUtils.getMethodInfo(getters[i]);
+ e = EmitUtils.begin_method(ce, getter, Constants.ACC_PUBLIC);
+ e.load_this();
+ e.getfield(FIELD_NAME);
+ e.invoke(getter);
+ e.return_value();
+ e.end_method();
+ }
+
+ for (int i = 0; i < setters.length; i++) {
+ MethodInfo setter = ReflectUtils.getMethodInfo(setters[i]);
+ e = EmitUtils.begin_method(ce, setter, Constants.ACC_PUBLIC);
+ e.throw_exception(ILLEGAL_STATE_EXCEPTION, "Bean is immutable");
+ e.end_method();
+ }
+
+ ce.end_class();
+ }
+
+ protected Object firstInstance(Class type) {
+ return ReflectUtils.newInstance(type, OBJECT_CLASSES, new Object[]{ bean });
+ }
+
+ // TODO: optimize
+ protected Object nextInstance(Object instance) {
+ return firstInstance(instance.getClass());
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/AbstractClassGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/AbstractClassGenerator.java
new file mode 100644
index 0000000..af80d77
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/AbstractClassGenerator.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.WeakHashMap;
+
+/**
+ * Abstract class for all code-generating CGLIB utilities.
+ * In addition to caching generated classes for performance, it provides hooks for
+ * customizing the <code>ClassLoader</code>, name of the generated class, and transformations
+ * applied before generation.
+ */
+abstract public class AbstractClassGenerator
+implements ClassGenerator
+{
+ private static final Object NAME_KEY = new Object();
+ private static final ThreadLocal CURRENT = new ThreadLocal();
+
+ private GeneratorStrategy strategy = DefaultGeneratorStrategy.INSTANCE;
+ private NamingPolicy namingPolicy = DefaultNamingPolicy.INSTANCE;
+ private Source source;
+ private ClassLoader classLoader;
+ private String namePrefix;
+ private Object key;
+ private boolean useCache = true;
+ private String className;
+ private boolean attemptLoad;
+
+ protected AbstractClassGenerator(Source source) {
+ this.source = source;
+ }
+
+ /**
+ * Used internally by CGLIB. Returns the <code>AbstractClassGenerator</code>
+ * that is being used to generate a class in the current thread.
+ */
+ public static AbstractClassGenerator getCurrent() {
+ return (AbstractClassGenerator)CURRENT.get();
+ }
+
+ protected void setNamePrefix(String namePrefix) {
+ this.namePrefix = namePrefix;
+ }
+
+ final protected String getClassName() {
+ if (className == null)
+ className = getClassName(getClassLoader());
+ return className;
+ }
+
+ private String getClassName(final ClassLoader loader) {
+ final Set nameCache = getClassNameCache(loader);
+ return namingPolicy.getClassName(namePrefix, source.name, key, new Predicate() {
+ public boolean evaluate(Object arg) {
+ return nameCache.contains(arg);
+ }
+ });
+ }
+
+ private Set getClassNameCache(ClassLoader loader) {
+ return (Set)((Map)source.cache.get(loader)).get(NAME_KEY);
+ }
+
+ /**
+ * @see #setNamingPolicy
+ */
+ public NamingPolicy getNamingPolicy() {
+ return namingPolicy;
+ }
+
+ /**
+ * Override the default naming policy.
+ * @see DefaultNamingPolicy
+ * @param namingPolicy the custom policy, or null to use the default
+ */
+ public void setNamingPolicy(NamingPolicy namingPolicy) {
+ if (namingPolicy == null)
+ namingPolicy = DefaultNamingPolicy.INSTANCE;
+ this.namingPolicy = namingPolicy;
+ }
+
+ /**
+ * @see #setUseCache
+ */
+ public boolean getUseCache() {
+ return useCache;
+ }
+
+ /**
+ * Whether use and update the static cache of generated classes
+ * for a class with the same properties. Default is <code>true</code>.
+ */
+ public void setUseCache(boolean useCache) {
+ this.useCache = useCache;
+ }
+
+ public boolean getAttemptLoad() {
+ return attemptLoad;
+ }
+
+ /**
+ * If set, CGLIB will attempt to load classes from the specified
+ * <code>ClassLoader</code> before generating them. Because generated
+ * class names are not guaranteed to be unique, the default is <code>false</code>.
+ */
+ public void setAttemptLoad(boolean attemptLoad) {
+ this.attemptLoad = attemptLoad;
+ }
+
+ /**
+ * @see #setStrategy
+ */
+ public GeneratorStrategy getStrategy() {
+ return strategy;
+ }
+
+ /**
+ * Set the strategy to use to create the bytecode from this generator.
+ * By default an instance of {@see DefaultGeneratorStrategy} is used.
+ */
+ public void setStrategy(GeneratorStrategy strategy) {
+ if (strategy == null)
+ strategy = DefaultGeneratorStrategy.INSTANCE;
+ this.strategy = strategy;
+ }
+
+ public ClassLoader getClassLoader() {
+ ClassLoader t = classLoader;
+ if (t == null) {
+ t = getDefaultClassLoader();
+ }
+ if (t == null) {
+ t = getClass().getClassLoader();
+ }
+ if (t == null) {
+ t = Thread.currentThread().getContextClassLoader();
+ }
+ if (t == null) {
+ throw new IllegalStateException("Cannot determine classloader");
+ }
+ return t;
+ }
+
+ /**
+ * Set the <code>ClassLoader</code> in which the class will be generated.
+ * Concrete subclasses of <code>AbstractClassGenerator</code> (such as <code>Enhancer</code>)
+ * will try to choose an appropriate default if this is unset.
+ * <p>
+ * Classes are cached per-<code>ClassLoader</code> using a <code>WeakHashMap</code>, to allow
+ * the generated classes to be removed when the associated loader is garbage collected.
+ * @param classLoader the loader to generate the new class with, or null to use the default
+ */
+ public void setClassLoader(ClassLoader classLoader) {
+ this.classLoader = classLoader;
+ }
+
+ abstract protected ClassLoader getDefaultClassLoader();
+
+ protected Object create(Object key) {
+ try {
+ Class gen = null;
+
+ synchronized (source) {
+ ClassLoader loader = getClassLoader();
+ Map cache2 = null;
+ cache2 = (Map)source.cache.get(loader);
+ if (cache2 == null) {
+ cache2 = new HashMap();
+ cache2.put(NAME_KEY, new HashSet());
+ source.cache.put(loader, cache2);
+ } else if (useCache) {
+ Reference ref = (Reference)cache2.get(key);
+ gen = (Class) (( ref == null ) ? null : ref.get());
+ }
+ if (gen == null) {
+ Object save = CURRENT.get();
+ CURRENT.set(this);
+ try {
+ this.key = key;
+
+ if (attemptLoad) {
+ try {
+ gen = loader.loadClass(getClassName());
+ } catch (ClassNotFoundException e) {
+ // ignore
+ }
+ }
+ if (gen == null) {
+ byte[] b = strategy.generate(this);
+ String className = ClassNameReader.getClassName(new ClassReader(b));
+ getClassNameCache(loader).add(className);
+ gen = ReflectUtils.defineClass(className, b, loader);
+ }
+
+ if (useCache) {
+ cache2.put(key, new WeakReference(gen));
+ }
+ return firstInstance(gen);
+ } finally {
+ CURRENT.set(save);
+ }
+ }
+ }
+ return firstInstance(gen);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Error e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ abstract protected Object firstInstance(Class type) throws Exception;
+
+ abstract protected Object nextInstance(Object instance) throws Exception;
+
+ protected static class Source {
+ String name;
+ Map cache = new WeakHashMap();
+ public Source(String name) {
+ this.name = name;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Block.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Block.java
new file mode 100644
index 0000000..e622ca9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Block.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+
+public class Block
+{
+ private CodeEmitter e;
+ private Label start;
+ private Label end;
+
+ public Block(CodeEmitter e) {
+ this.e = e;
+ start = e.mark();
+ }
+
+ public CodeEmitter getCodeEmitter() {
+ return e;
+ }
+
+ public void end() {
+ if (end != null) {
+ throw new IllegalStateException("end of label already set");
+ }
+ end = e.mark();
+ }
+
+ public Label getStart() {
+ return start;
+ }
+
+ public Label getEnd() {
+ return end;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassEmitter.java
new file mode 100644
index 0000000..798c844
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassEmitter.java
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassAdapter;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodAdapter;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Juozas Baliuka, Chris Nokleberg
+ */
+public class ClassEmitter extends ClassAdapter {
+ private static int hookCounter;
+ private ClassInfo classInfo;
+ private Map fieldInfo;
+ private MethodVisitor rawStaticInit;
+ private CodeEmitter staticInit;
+ private CodeEmitter staticHook;
+ private Signature staticHookSig;
+
+ public ClassEmitter(ClassVisitor cv) {
+ super(null);
+ setTarget(cv);
+ }
+
+ public ClassEmitter() {
+ super(null);
+ }
+
+ synchronized private static int getNextHook() {
+ return ++hookCounter;
+ }
+
+ public void setTarget(ClassVisitor cv) {
+ this.cv = cv;
+ fieldInfo = new HashMap();
+
+ // just to be safe
+ staticInit = staticHook = null;
+ staticHookSig = null;
+ }
+
+ public ClassInfo getClassInfo() {
+ return classInfo;
+ }
+
+ public void begin_class(int version, final int access, String className, final Type superType, final Type[] interfaces, String source) {
+ final Type classType = Type.getType("L" + className.replace('.', '/') + ";");
+ classInfo = new ClassInfo() {
+ public Type getType() {
+ return classType;
+ }
+ public Type getSuperType() {
+ return (superType != null) ? superType : Constants.TYPE_OBJECT;
+ }
+ public Type[] getInterfaces() {
+ return interfaces;
+ }
+ public int getModifiers() {
+ return access;
+ }
+ };
+ cv.visit(version,
+ access,
+ classInfo.getType().getInternalName(),
+ null,
+ classInfo.getSuperType().getInternalName(),
+ TypeUtils.toInternalNames(interfaces));
+ if (source != null)
+ cv.visitSource(source, null);
+ init();
+ }
+
+ public CodeEmitter getStaticHook() {
+ if (TypeUtils.isInterface(getAccess())) {
+ throw new IllegalStateException("static hook is invalid for this class");
+ }
+ if (staticHook == null) {
+ staticHookSig = new Signature("CGLIB$STATICHOOK" + getNextHook(), "()V");
+ staticHook = begin_method(Constants.ACC_STATIC,
+ staticHookSig,
+ null);
+ if (staticInit != null) {
+ staticInit.invoke_static_this(staticHookSig);
+ }
+ }
+ return staticHook;
+ }
+
+ protected void init() {
+ }
+
+ public int getAccess() {
+ return classInfo.getModifiers();
+ }
+
+ public Type getClassType() {
+ return classInfo.getType();
+ }
+
+ public Type getSuperType() {
+ return classInfo.getSuperType();
+ }
+
+ public void end_class() {
+ if (staticHook != null && staticInit == null) {
+ // force creation of static init
+ begin_static();
+ }
+ if (staticInit != null) {
+ staticHook.return_value();
+ staticHook.end_method();
+ rawStaticInit.visitInsn(Constants.RETURN);
+ rawStaticInit.visitMaxs(0, 0);
+ staticInit = staticHook = null;
+ staticHookSig = null;
+ }
+ cv.visitEnd();
+ }
+
+ public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
+ if (classInfo == null)
+ throw new IllegalStateException("classInfo is null! " + this);
+ MethodVisitor v = cv.visitMethod(access,
+ sig.getName(),
+ sig.getDescriptor(),
+ null,
+ TypeUtils.toInternalNames(exceptions));
+ if (sig.equals(Constants.SIG_STATIC) && !TypeUtils.isInterface(getAccess())) {
+ rawStaticInit = v;
+ MethodVisitor wrapped = new MethodAdapter(v) {
+ public void visitMaxs(int maxStack, int maxLocals) {
+ // ignore
+ }
+ public void visitInsn(int insn) {
+ if (insn != Constants.RETURN) {
+ super.visitInsn(insn);
+ }
+ }
+ };
+ staticInit = new CodeEmitter(this, wrapped, access, sig, exceptions);
+ if (staticHook == null) {
+ // force static hook creation
+ getStaticHook();
+ } else {
+ staticInit.invoke_static_this(staticHookSig);
+ }
+ return staticInit;
+ } else if (sig.equals(staticHookSig)) {
+ return new CodeEmitter(this, v, access, sig, exceptions) {
+ public boolean isStaticHook() {
+ return true;
+ }
+ };
+ } else {
+ return new CodeEmitter(this, v, access, sig, exceptions);
+ }
+ }
+
+ public CodeEmitter begin_static() {
+ return begin_method(Constants.ACC_STATIC, Constants.SIG_STATIC, null);
+ }
+
+ public void declare_field(int access, String name, Type type, Object value) {
+ FieldInfo existing = (FieldInfo)fieldInfo.get(name);
+ FieldInfo info = new FieldInfo(access, name, type, value);
+ if (existing != null) {
+ if (!info.equals(existing)) {
+ throw new IllegalArgumentException("Field \"" + name + "\" has been declared differently");
+ }
+ } else {
+ fieldInfo.put(name, info);
+ cv.visitField(access, name, type.getDescriptor(), null, value);
+ }
+ }
+
+ // TODO: make public?
+ boolean isFieldDeclared(String name) {
+ return fieldInfo.get(name) != null;
+ }
+
+ FieldInfo getFieldInfo(String name) {
+ FieldInfo field = (FieldInfo)fieldInfo.get(name);
+ if (field == null) {
+ throw new IllegalArgumentException("Field " + name + " is not declared in " + getClassType().getClassName());
+ }
+ return field;
+ }
+
+ public void visit(int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ begin_class(version,
+ access,
+ name.replace('/', '.'),
+ TypeUtils.fromInternalName(superName),
+ TypeUtils.fromInternalNames(interfaces),
+ null); // TODO
+ }
+
+ public void visitEnd() {
+ end_class();
+ }
+
+ public FieldVisitor visitField(int access,
+ String name,
+ String desc,
+ String signature,
+ Object value) {
+ declare_field(access, name, Type.getType(desc), value);
+ return null; // TODO
+ }
+
+ public MethodVisitor visitMethod(int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ return begin_method(access,
+ new Signature(name, desc),
+ TypeUtils.fromInternalNames(exceptions));
+ }
+
+ static class FieldInfo {
+ int access;
+ String name;
+ Type type;
+ Object value;
+
+ public FieldInfo(int access, String name, Type type, Object value) {
+ this.access = access;
+ this.name = name;
+ this.type = type;
+ this.value = value;
+ }
+
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (!(o instanceof FieldInfo))
+ return false;
+ FieldInfo other = (FieldInfo)o;
+ if (access != other.access ||
+ !name.equals(other.name) ||
+ !type.equals(other.type)) {
+ return false;
+ }
+ if ((value == null) ^ (other.value == null))
+ return false;
+ if (value != null && !value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ public int hashCode() {
+ return access ^ name.hashCode() ^ type.hashCode() ^ ((value == null) ? 0 : value.hashCode());
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassGenerator.java
new file mode 100644
index 0000000..4fcb97a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassGenerator.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+
+public interface ClassGenerator {
+ void generateClass(ClassVisitor v) throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassInfo.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassInfo.java
new file mode 100644
index 0000000..fb1561e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassInfo.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+abstract public class ClassInfo {
+
+ protected ClassInfo() {
+ }
+
+ abstract public Type getType();
+ abstract public Type getSuperType();
+ abstract public Type[] getInterfaces();
+ abstract public int getModifiers();
+
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (!(o instanceof ClassInfo))
+ return false;
+ return getType().equals(((ClassInfo)o).getType());
+ }
+
+ public int hashCode() {
+ return getType().hashCode();
+ }
+
+ public String toString() {
+ // TODO: include modifiers, superType, interfaces
+ return getType().getClassName();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassNameReader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassNameReader.java
new file mode 100644
index 0000000..eadd820
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassNameReader.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassAdapter;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// TODO: optimize (ClassReader buffers entire class before accept)
+public class ClassNameReader {
+ private static final EarlyExitException EARLY_EXIT = new EarlyExitException();
+
+ private ClassNameReader() {
+ }
+
+ public static String getClassName(ClassReader r) {
+
+ return getClassInfo(r)[0];
+
+ }
+
+ public static String[] getClassInfo(ClassReader r) {
+ final List array = new ArrayList();
+ try {
+ r.accept(new ClassAdapter(null) {
+ public void visit(int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ array.add( name.replace('/', '.') );
+ if(superName != null){
+ array.add( superName.replace('/', '.') );
+ }
+ for(int i = 0; i < interfaces.length; i++ ){
+ array.add( interfaces[i].replace('/', '.') );
+ }
+
+ throw EARLY_EXIT;
+ }
+ }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+ } catch (EarlyExitException e) { }
+
+ return (String[])array.toArray( new String[]{} );
+ }
+
+ private static class EarlyExitException extends RuntimeException { }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassesKey.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassesKey.java
new file mode 100644
index 0000000..4996381
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ClassesKey.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+public class ClassesKey {
+ private static final Key FACTORY = (Key)KeyFactory.create(Key.class, KeyFactory.OBJECT_BY_CLASS);
+
+ private ClassesKey() {
+ }
+
+ public static Object create(Object[] array) {
+ return FACTORY.newInstance(array);
+ }
+
+ interface Key {
+ Object newInstance(Object[] array);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeEmitter.java
new file mode 100644
index 0000000..11f8da2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeEmitter.java
@@ -0,0 +1,851 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.Arrays;
+
+/**
+ * @author Juozas Baliuka, Chris Nokleberg
+ */
+public class CodeEmitter extends LocalVariablesSorter {
+ public static final int ADD = Constants.IADD;
+ public static final int MUL = Constants.IMUL;
+ public static final int XOR = Constants.IXOR;
+ public static final int USHR = Constants.IUSHR;
+ public static final int SUB = Constants.ISUB;
+ public static final int DIV = Constants.IDIV;
+ public static final int NEG = Constants.INEG;
+ public static final int REM = Constants.IREM;
+ public static final int AND = Constants.IAND;
+ public static final int OR = Constants.IOR;
+ public static final int GT = Constants.IFGT;
+ public static final int LT = Constants.IFLT;
+ public static final int GE = Constants.IFGE;
+ public static final int LE = Constants.IFLE;
+ public static final int NE = Constants.IFNE;
+ public static final int EQ = Constants.IFEQ;
+ private static final Signature BOOLEAN_VALUE =
+ TypeUtils.parseSignature("boolean booleanValue()");
+ private static final Signature CHAR_VALUE =
+ TypeUtils.parseSignature("char charValue()");
+ private static final Signature LONG_VALUE =
+ TypeUtils.parseSignature("long longValue()");
+ private static final Signature DOUBLE_VALUE =
+ TypeUtils.parseSignature("double doubleValue()");
+ private static final Signature FLOAT_VALUE =
+ TypeUtils.parseSignature("float floatValue()");
+ private static final Signature INT_VALUE =
+ TypeUtils.parseSignature("int intValue()");
+ private static final Signature CSTRUCT_NULL =
+ TypeUtils.parseConstructor("");
+ private static final Signature CSTRUCT_STRING =
+ TypeUtils.parseConstructor("String");
+ private ClassEmitter ce;
+ private State state;
+
+ CodeEmitter(ClassEmitter ce, MethodVisitor mv, int access, Signature sig, Type[] exceptionTypes) {
+ super(access, sig.getDescriptor(), mv);
+ this.ce = ce;
+ state = new State(ce.getClassInfo(), access, sig, exceptionTypes);
+ }
+
+ public CodeEmitter(CodeEmitter wrap) {
+ super(wrap);
+ this.ce = wrap.ce;
+ this.state = wrap.state;
+ }
+
+ private static boolean isSorted(int[] keys) {
+ for (int i = 1; i < keys.length; i++) {
+ if (keys[i] < keys[i - 1])
+ return false;
+ }
+ return true;
+ }
+
+ public boolean isStaticHook() {
+ return false;
+ }
+
+ public Signature getSignature() {
+ return state.sig;
+ }
+
+ public Type getReturnType() {
+ return state.sig.getReturnType();
+ }
+
+ public MethodInfo getMethodInfo() {
+ return state;
+ }
+
+ public ClassEmitter getClassEmitter() {
+ return ce;
+ }
+
+ public void end_method() {
+ visitMaxs(0, 0);
+ }
+
+ public Block begin_block() {
+ return new Block(this);
+ }
+
+ public void catch_exception(Block block, Type exception) {
+ if (block.getEnd() == null) {
+ throw new IllegalStateException("end of block is unset");
+ }
+ mv.visitTryCatchBlock(block.getStart(),
+ block.getEnd(),
+ mark(),
+ exception.getInternalName());
+ }
+
+ public void goTo(Label label) { mv.visitJumpInsn(Constants.GOTO, label); }
+ public void ifnull(Label label) { mv.visitJumpInsn(Constants.IFNULL, label); }
+ public void ifnonnull(Label label) { mv.visitJumpInsn(Constants.IFNONNULL, label); }
+
+ public void if_jump(int mode, Label label) {
+ mv.visitJumpInsn(mode, label);
+ }
+
+ public void if_icmp(int mode, Label label) {
+ if_cmp(Type.INT_TYPE, mode, label);
+ }
+
+ public void if_cmp(Type type, int mode, Label label) {
+ int intOp = -1;
+ int jumpmode = mode;
+ switch (mode) {
+ case GE: jumpmode = LT; break;
+ case LE: jumpmode = GT; break;
+ }
+ switch (type.getSort()) {
+ case Type.LONG:
+ mv.visitInsn(Constants.LCMP);
+ break;
+ case Type.DOUBLE:
+ mv.visitInsn(Constants.DCMPG);
+ break;
+ case Type.FLOAT:
+ mv.visitInsn(Constants.FCMPG);
+ break;
+ case Type.ARRAY:
+ case Type.OBJECT:
+ switch (mode) {
+ case EQ:
+ mv.visitJumpInsn(Constants.IF_ACMPEQ, label);
+ return;
+ case NE:
+ mv.visitJumpInsn(Constants.IF_ACMPNE, label);
+ return;
+ }
+ throw new IllegalArgumentException("Bad comparison for type " + type);
+ default:
+ switch (mode) {
+ case EQ: intOp = Constants.IF_ICMPEQ; break;
+ case NE: intOp = Constants.IF_ICMPNE; break;
+ case GE: swap(); /* fall through */
+ case LT: intOp = Constants.IF_ICMPLT; break;
+ case LE: swap(); /* fall through */
+ case GT: intOp = Constants.IF_ICMPGT; break;
+ }
+ mv.visitJumpInsn(intOp, label);
+ return;
+ }
+ if_jump(jumpmode, label);
+ }
+
+ public void pop() { mv.visitInsn(Constants.POP); }
+ public void pop2() { mv.visitInsn(Constants.POP2); }
+ public void dup() { mv.visitInsn(Constants.DUP); }
+ public void dup2() { mv.visitInsn(Constants.DUP2); }
+ public void dup_x1() { mv.visitInsn(Constants.DUP_X1); }
+ public void dup_x2() { mv.visitInsn(Constants.DUP_X2); }
+ public void dup2_x1() { mv.visitInsn(Constants.DUP2_X1); }
+ public void dup2_x2() { mv.visitInsn(Constants.DUP2_X2); }
+ public void swap() { mv.visitInsn(Constants.SWAP); }
+ public void aconst_null() { mv.visitInsn(Constants.ACONST_NULL); }
+
+ public void swap(Type prev, Type type) {
+ if (type.getSize() == 1) {
+ if (prev.getSize() == 1) {
+ swap(); // same as dup_x1(), pop();
+ } else {
+ dup_x2();
+ pop();
+ }
+ } else {
+ if (prev.getSize() == 1) {
+ dup2_x1();
+ pop2();
+ } else {
+ dup2_x2();
+ pop2();
+ }
+ }
+ }
+
+ public void monitorenter() { mv.visitInsn(Constants.MONITORENTER); }
+ public void monitorexit() { mv.visitInsn(Constants.MONITOREXIT); }
+
+ public void math(int op, Type type) { mv.visitInsn(type.getOpcode(op)); }
+
+ public void array_load(Type type) { mv.visitInsn(type.getOpcode(Constants.IALOAD)); }
+ public void array_store(Type type) { mv.visitInsn(type.getOpcode(Constants.IASTORE)); }
+
+ /**
+ * Casts from one primitive numeric type to another
+ */
+ public void cast_numeric(Type from, Type to) {
+ if (from != to) {
+ if (from == Type.DOUBLE_TYPE) {
+ if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Constants.D2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Constants.D2L);
+ } else {
+ mv.visitInsn(Constants.D2I);
+ cast_numeric(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.FLOAT_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Constants.F2D);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Constants.F2L);
+ } else {
+ mv.visitInsn(Constants.F2I);
+ cast_numeric(Type.INT_TYPE, to);
+ }
+ } else if (from == Type.LONG_TYPE) {
+ if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Constants.L2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Constants.L2F);
+ } else {
+ mv.visitInsn(Constants.L2I);
+ cast_numeric(Type.INT_TYPE, to);
+ }
+ } else {
+ if (to == Type.BYTE_TYPE) {
+ mv.visitInsn(Constants.I2B);
+ } else if (to == Type.CHAR_TYPE) {
+ mv.visitInsn(Constants.I2C);
+ } else if (to == Type.DOUBLE_TYPE) {
+ mv.visitInsn(Constants.I2D);
+ } else if (to == Type.FLOAT_TYPE) {
+ mv.visitInsn(Constants.I2F);
+ } else if (to == Type.LONG_TYPE) {
+ mv.visitInsn(Constants.I2L);
+ } else if (to == Type.SHORT_TYPE) {
+ mv.visitInsn(Constants.I2S);
+ }
+ }
+ }
+ }
+
+ public void push(int i) {
+ if (i < -1) {
+ mv.visitLdcInsn(new Integer(i));
+ } else if (i <= 5) {
+ mv.visitInsn(TypeUtils.ICONST(i));
+ } else if (i <= Byte.MAX_VALUE) {
+ mv.visitIntInsn(Constants.BIPUSH, i);
+ } else if (i <= Short.MAX_VALUE) {
+ mv.visitIntInsn(Constants.SIPUSH, i);
+ } else {
+ mv.visitLdcInsn(new Integer(i));
+ }
+ }
+
+ public void push(long value) {
+ if (value == 0L || value == 1L) {
+ mv.visitInsn(TypeUtils.LCONST(value));
+ } else {
+ mv.visitLdcInsn(new Long(value));
+ }
+ }
+
+ public void push(float value) {
+ if (value == 0f || value == 1f || value == 2f) {
+ mv.visitInsn(TypeUtils.FCONST(value));
+ } else {
+ mv.visitLdcInsn(new Float(value));
+ }
+ }
+ public void push(double value) {
+ if (value == 0d || value == 1d) {
+ mv.visitInsn(TypeUtils.DCONST(value));
+ } else {
+ mv.visitLdcInsn(new Double(value));
+ }
+ }
+
+ public void push(String value) {
+ mv.visitLdcInsn(value);
+ }
+
+ public void newarray() {
+ newarray(Constants.TYPE_OBJECT);
+ }
+
+ public void newarray(Type type) {
+ if (TypeUtils.isPrimitive(type)) {
+ mv.visitIntInsn(Constants.NEWARRAY, TypeUtils.NEWARRAY(type));
+ } else {
+ emit_type(Constants.ANEWARRAY, type);
+ }
+ }
+
+ public void arraylength() {
+ mv.visitInsn(Constants.ARRAYLENGTH);
+ }
+
+ public void load_this() {
+ if (TypeUtils.isStatic(state.access)) {
+ throw new IllegalStateException("no 'this' pointer within static method");
+ }
+ mv.visitVarInsn(Constants.ALOAD, 0);
+ }
+
+ /**
+ * Pushes all of the arguments of the current method onto the stack.
+ */
+ public void load_args() {
+ load_args(0, state.argumentTypes.length);
+ }
+
+ /**
+ * Pushes the specified argument of the current method onto the stack.
+ * @param index the zero-based index into the argument list
+ */
+ public void load_arg(int index) {
+ load_local(state.argumentTypes[index],
+ state.localOffset + skipArgs(index));
+ }
+
+ // zero-based (see load_this)
+ public void load_args(int fromArg, int count) {
+ int pos = state.localOffset + skipArgs(fromArg);
+ for (int i = 0; i < count; i++) {
+ Type t = state.argumentTypes[fromArg + i];
+ load_local(t, pos);
+ pos += t.getSize();
+ }
+ }
+
+ private int skipArgs(int numArgs) {
+ int amount = 0;
+ for (int i = 0; i < numArgs; i++) {
+ amount += state.argumentTypes[i].getSize();
+ }
+ return amount;
+ }
+
+ private void load_local(Type t, int pos) {
+ // TODO: make t == null ok?
+ mv.visitVarInsn(t.getOpcode(Constants.ILOAD), pos);
+ }
+
+ private void store_local(Type t, int pos) {
+ // TODO: make t == null ok?
+ mv.visitVarInsn(t.getOpcode(Constants.ISTORE), pos);
+ }
+
+ public void iinc(Local local, int amount) {
+ mv.visitIincInsn(local.getIndex(), amount);
+ }
+
+ public void store_local(Local local) {
+ store_local(local.getType(), local.getIndex());
+ }
+
+ public void load_local(Local local) {
+ load_local(local.getType(), local.getIndex());
+ }
+
+ public void return_value() {
+ mv.visitInsn(state.sig.getReturnType().getOpcode(Constants.IRETURN));
+ }
+
+ public void getfield(String name) {
+ ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
+ int opcode = TypeUtils.isStatic(info.access) ? Constants.GETSTATIC : Constants.GETFIELD;
+ emit_field(opcode, ce.getClassType(), name, info.type);
+ }
+
+ public void putfield(String name) {
+ ClassEmitter.FieldInfo info = ce.getFieldInfo(name);
+ int opcode = TypeUtils.isStatic(info.access) ? Constants.PUTSTATIC : Constants.PUTFIELD;
+ emit_field(opcode, ce.getClassType(), name, info.type);
+ }
+
+ public void super_getfield(String name, Type type) {
+ emit_field(Constants.GETFIELD, ce.getSuperType(), name, type);
+ }
+
+ public void super_putfield(String name, Type type) {
+ emit_field(Constants.PUTFIELD, ce.getSuperType(), name, type);
+ }
+
+ public void super_getstatic(String name, Type type) {
+ emit_field(Constants.GETSTATIC, ce.getSuperType(), name, type);
+ }
+
+ public void super_putstatic(String name, Type type) {
+ emit_field(Constants.PUTSTATIC, ce.getSuperType(), name, type);
+ }
+
+ public void getfield(Type owner, String name, Type type) {
+ emit_field(Constants.GETFIELD, owner, name, type);
+ }
+
+ public void putfield(Type owner, String name, Type type) {
+ emit_field(Constants.PUTFIELD, owner, name, type);
+ }
+
+ public void getstatic(Type owner, String name, Type type) {
+ emit_field(Constants.GETSTATIC, owner, name, type);
+ }
+
+ public void putstatic(Type owner, String name, Type type) {
+ emit_field(Constants.PUTSTATIC, owner, name, type);
+ }
+
+ // package-protected for EmitUtils, try to fix
+ void emit_field(int opcode, Type ctype, String name, Type ftype) {
+ mv.visitFieldInsn(opcode,
+ ctype.getInternalName(),
+ name,
+ ftype.getDescriptor());
+ }
+
+ public void super_invoke() {
+ super_invoke(state.sig);
+ }
+
+ public void super_invoke(Signature sig) {
+ emit_invoke(Constants.INVOKESPECIAL, ce.getSuperType(), sig);
+ }
+
+ public void invoke_constructor(Type type) {
+ invoke_constructor(type, CSTRUCT_NULL);
+ }
+
+ public void super_invoke_constructor() {
+ invoke_constructor(ce.getSuperType());
+ }
+
+ public void invoke_constructor_this() {
+ invoke_constructor(ce.getClassType());
+ }
+
+ private void emit_invoke(int opcode, Type type, Signature sig) {
+ if (sig.getName().equals(Constants.CONSTRUCTOR_NAME) &&
+ ((opcode == Constants.INVOKEVIRTUAL) ||
+ (opcode == Constants.INVOKESTATIC))) {
+ // TODO: error
+ }
+ mv.visitMethodInsn(opcode,
+ type.getInternalName(),
+ sig.getName(),
+ sig.getDescriptor());
+ }
+
+ public void invoke_interface(Type owner, Signature sig) {
+ emit_invoke(Constants.INVOKEINTERFACE, owner, sig);
+ }
+
+ public void invoke_virtual(Type owner, Signature sig) {
+ emit_invoke(Constants.INVOKEVIRTUAL, owner, sig);
+ }
+
+ public void invoke_static(Type owner, Signature sig) {
+ emit_invoke(Constants.INVOKESTATIC, owner, sig);
+ }
+
+ public void invoke_virtual_this(Signature sig) {
+ invoke_virtual(ce.getClassType(), sig);
+ }
+
+ public void invoke_static_this(Signature sig) {
+ invoke_static(ce.getClassType(), sig);
+ }
+
+ public void invoke_constructor(Type type, Signature sig) {
+ emit_invoke(Constants.INVOKESPECIAL, type, sig);
+ }
+
+ public void invoke_constructor_this(Signature sig) {
+ invoke_constructor(ce.getClassType(), sig);
+ }
+
+ public void super_invoke_constructor(Signature sig) {
+ invoke_constructor(ce.getSuperType(), sig);
+ }
+
+ public void new_instance_this() {
+ new_instance(ce.getClassType());
+ }
+
+ public void new_instance(Type type) {
+ emit_type(Constants.NEW, type);
+ }
+
+ private void emit_type(int opcode, Type type) {
+ String desc;
+ if (TypeUtils.isArray(type)) {
+ desc = type.getDescriptor();
+ } else {
+ desc = type.getInternalName();
+ }
+ mv.visitTypeInsn(opcode, desc);
+ }
+
+ public void aaload(int index) {
+ push(index);
+ aaload();
+ }
+
+ public void aaload() { mv.visitInsn(Constants.AALOAD); }
+ public void aastore() { mv.visitInsn(Constants.AASTORE); }
+ public void athrow() { mv.visitInsn(Constants.ATHROW); }
+
+ public Label make_label() {
+ return new Label();
+ }
+
+ public Local make_local() {
+ return make_local(Constants.TYPE_OBJECT);
+ }
+
+ public Local make_local(Type type) {
+ return new Local(newLocal(type.getSize()), type);
+ }
+
+ public void checkcast_this() {
+ checkcast(ce.getClassType());
+ }
+
+ public void checkcast(Type type) {
+ if (!type.equals(Constants.TYPE_OBJECT)) {
+ emit_type(Constants.CHECKCAST, type);
+ }
+ }
+
+ public void instance_of(Type type) {
+ emit_type(Constants.INSTANCEOF, type);
+ }
+
+ public void instance_of_this() {
+ instance_of(ce.getClassType());
+ }
+
+ public void process_switch(int[] keys, ProcessSwitchCallback callback) {
+ float density;
+ if (keys.length == 0) {
+ density = 0;
+ } else {
+ density = (float)keys.length / (keys[keys.length - 1] - keys[0] + 1);
+ }
+ process_switch(keys, callback, density >= 0.5f);
+ }
+
+ public void process_switch(int[] keys, ProcessSwitchCallback callback, boolean useTable) {
+ if (!isSorted(keys))
+ throw new IllegalArgumentException("keys to switch must be sorted ascending");
+ Label def = make_label();
+ Label end = make_label();
+
+ try {
+ if (keys.length > 0) {
+ int len = keys.length;
+ int min = keys[0];
+ int max = keys[len - 1];
+ int range = max - min + 1;
+
+ if (useTable) {
+ Label[] labels = new Label[range];
+ Arrays.fill(labels, def);
+ for (int i = 0; i < len; i++) {
+ labels[keys[i] - min] = make_label();
+ }
+ mv.visitTableSwitchInsn(min, max, def, labels);
+ for (int i = 0; i < range; i++) {
+ Label label = labels[i];
+ if (label != def) {
+ mark(label);
+ callback.processCase(i + min, end);
+ }
+ }
+ } else {
+ Label[] labels = new Label[len];
+ for (int i = 0; i < len; i++) {
+ labels[i] = make_label();
+ }
+ mv.visitLookupSwitchInsn(def, keys, labels);
+ for (int i = 0; i < len; i++) {
+ mark(labels[i]);
+ callback.processCase(keys[i], end);
+ }
+ }
+ }
+
+ mark(def);
+ callback.processDefault();
+ mark(end);
+
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Error e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ public void mark(Label label) {
+ mv.visitLabel(label);
+ }
+
+ Label mark() {
+ Label label = make_label();
+ mv.visitLabel(label);
+ return label;
+ }
+
+ public void push(boolean value) {
+ push(value ? 1 : 0);
+ }
+
+ /**
+ * Toggles the integer on the top of the stack from 1 to 0 or vice versa
+ */
+ public void not() {
+ push(1);
+ math(XOR, Type.INT_TYPE);
+ }
+
+ public void throw_exception(Type type, String msg) {
+ new_instance(type);
+ dup();
+ push(msg);
+ invoke_constructor(type, CSTRUCT_STRING);
+ athrow();
+ }
+
+ /**
+ * If the argument is a primitive class, replaces the primitive value
+ * on the top of the stack with the wrapped (Object) equivalent. For
+ * example, char -> Character.
+ * If the class is Void, a null is pushed onto the stack instead.
+ * @param type the class indicating the current type of the top stack value
+ */
+ public void box(Type type) {
+ if (TypeUtils.isPrimitive(type)) {
+ if (type == Type.VOID_TYPE) {
+ aconst_null();
+ } else {
+ Type boxed = TypeUtils.getBoxedType(type);
+ new_instance(boxed);
+ if (type.getSize() == 2) {
+ // Pp -> Ppo -> oPpo -> ooPpo -> ooPp -> o
+ dup_x2();
+ dup_x2();
+ pop();
+ } else {
+ // p -> po -> opo -> oop -> o
+ dup_x1();
+ swap();
+ }
+ invoke_constructor(boxed, new Signature(Constants.CONSTRUCTOR_NAME, Type.VOID_TYPE, new Type[]{ type }));
+ }
+ }
+ }
+
+ /**
+ * If the argument is a primitive class, replaces the object
+ * on the top of the stack with the unwrapped (primitive)
+ * equivalent. For example, Character -> char.
+ * @param type the class indicating the desired type of the top stack value
+ * @return true if the value was unboxed
+ */
+ public void unbox(Type type) {
+ Type t = Constants.TYPE_NUMBER;
+ Signature sig = null;
+ switch (type.getSort()) {
+ case Type.VOID:
+ return;
+ case Type.CHAR:
+ t = Constants.TYPE_CHARACTER;
+ sig = CHAR_VALUE;
+ break;
+ case Type.BOOLEAN:
+ t = Constants.TYPE_BOOLEAN;
+ sig = BOOLEAN_VALUE;
+ break;
+ case Type.DOUBLE:
+ sig = DOUBLE_VALUE;
+ break;
+ case Type.FLOAT:
+ sig = FLOAT_VALUE;
+ break;
+ case Type.LONG:
+ sig = LONG_VALUE;
+ break;
+ case Type.INT:
+ case Type.SHORT:
+ case Type.BYTE:
+ sig = INT_VALUE;
+ }
+
+ if (sig == null) {
+ checkcast(type);
+ } else {
+ checkcast(t);
+ invoke_virtual(t, sig);
+ }
+ }
+
+ /**
+ * Allocates and fills an Object[] array with the arguments to the
+ * current method. Primitive values are inserted as their boxed
+ * (Object) equivalents.
+ */
+ public void create_arg_array() {
+ /* generates:
+ Object[] args = new Object[]{ arg1, new Integer(arg2) };
+ */
+
+ push(state.argumentTypes.length);
+ newarray();
+ for (int i = 0; i < state.argumentTypes.length; i++) {
+ dup();
+ push(i);
+ load_arg(i);
+ box(state.argumentTypes[i]);
+ aastore();
+ }
+ }
+
+ /**
+ * Pushes a zero onto the stack if the argument is a primitive class, or a null otherwise.
+ */
+ public void zero_or_null(Type type) {
+ if (TypeUtils.isPrimitive(type)) {
+ switch (type.getSort()) {
+ case Type.DOUBLE:
+ push(0d);
+ break;
+ case Type.LONG:
+ push(0L);
+ break;
+ case Type.FLOAT:
+ push(0f);
+ break;
+ case Type.VOID:
+ aconst_null();
+ default:
+ push(0);
+ }
+ } else {
+ aconst_null();
+ }
+ }
+
+ /**
+ * Unboxes the object on the top of the stack. If the object is null, the
+ * unboxed primitive value becomes zero.
+ */
+ public void unbox_or_zero(Type type) {
+ if (TypeUtils.isPrimitive(type)) {
+ if (type != Type.VOID_TYPE) {
+ Label nonNull = make_label();
+ Label end = make_label();
+ dup();
+ ifnonnull(nonNull);
+ pop();
+ zero_or_null(type);
+ goTo(end);
+ mark(nonNull);
+ unbox(type);
+ mark(end);
+ }
+ } else {
+ checkcast(type);
+ }
+ }
+
+ public void visitMaxs(int maxStack, int maxLocals) {
+ if (!TypeUtils.isAbstract(state.access)) {
+ mv.visitMaxs(0, 0);
+ }
+ }
+
+ public void invoke(MethodInfo method, Type virtualType) {
+ ClassInfo classInfo = method.getClassInfo();
+ Type type = classInfo.getType();
+ Signature sig = method.getSignature();
+ if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
+ invoke_constructor(type, sig);
+ } else if (TypeUtils.isInterface(classInfo.getModifiers())) {
+ invoke_interface(type, sig);
+ } else if (TypeUtils.isStatic(method.getModifiers())) {
+ invoke_static(type, sig);
+ } else {
+ invoke_virtual(virtualType, sig);
+ }
+ }
+
+ public void invoke(MethodInfo method) {
+ invoke(method, method.getClassInfo().getType());
+ }
+
+ private static class State
+ extends MethodInfo
+ {
+ ClassInfo classInfo;
+ int access;
+ Signature sig;
+ Type[] argumentTypes;
+ int localOffset;
+ Type[] exceptionTypes;
+
+ State(ClassInfo classInfo, int access, Signature sig, Type[] exceptionTypes) {
+ this.classInfo = classInfo;
+ this.access = access;
+ this.sig = sig;
+ this.exceptionTypes = exceptionTypes;
+ localOffset = TypeUtils.isStatic(access) ? 0 : 1;
+ argumentTypes = sig.getArgumentTypes();
+ }
+
+ public ClassInfo getClassInfo() {
+ return classInfo;
+ }
+
+ public int getModifiers() {
+ return access;
+ }
+
+ public Signature getSignature() {
+ return sig;
+ }
+
+ public Type[] getExceptionTypes() {
+ return exceptionTypes;
+ }
+
+ public Attribute getAttribute() {
+ // TODO
+ return null;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeGenerationException.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeGenerationException.java
new file mode 100644
index 0000000..dc7a485
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CodeGenerationException.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+/**
+ * @version $Id: CodeGenerationException.java,v 1.3 2004/06/24 21:15:21 herbyderby Exp $
+ */
+public class CodeGenerationException extends RuntimeException {
+ private Throwable cause;
+
+ public CodeGenerationException(Throwable cause) {
+ super(cause.getClass().getName() + "-->" + cause.getMessage());
+ this.cause = cause;
+ }
+
+ public Throwable getCause() {
+ return cause;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CollectionUtils.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CollectionUtils.java
new file mode 100644
index 0000000..86412c8
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/CollectionUtils.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Chris Nokleberg
+ * @version $Id: CollectionUtils.java,v 1.7 2004/06/24 21:15:21 herbyderby Exp $
+ */
+public class CollectionUtils {
+ private CollectionUtils() { }
+
+ public static Map bucket(Collection c, Transformer t) {
+ Map buckets = new HashMap();
+ for (Iterator it = c.iterator(); it.hasNext();) {
+ Object value = (Object)it.next();
+ Object key = t.transform(value);
+ List bucket = (List)buckets.get(key);
+ if (bucket == null) {
+ buckets.put(key, bucket = new LinkedList());
+ }
+ bucket.add(value);
+ }
+ return buckets;
+ }
+
+ public static void reverse(Map source, Map target) {
+ for (Iterator it = source.keySet().iterator(); it.hasNext();) {
+ Object key = it.next();
+ target.put(source.get(key), key);
+ }
+ }
+
+ public static Collection filter(Collection c, Predicate p) {
+ Iterator it = c.iterator();
+ while (it.hasNext()) {
+ if (!p.evaluate(it.next())) {
+ it.remove();
+ }
+ }
+ return c;
+ }
+
+ public static List transform(Collection c, Transformer t) {
+ List result = new ArrayList(c.size());
+ for (Iterator it = c.iterator(); it.hasNext();) {
+ result.add(t.transform(it.next()));
+ }
+ return result;
+ }
+
+ public static Map getIndexMap(List list) {
+ Map indexes = new HashMap();
+ int index = 0;
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ indexes.put(it.next(), new Integer(index++));
+ }
+ return indexes;
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Constants.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Constants.java
new file mode 100644
index 0000000..ea19de7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Constants.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * @author Juozas Baliuka <a href="mailto:baliuka at mwm.lt">baliuka at mwm.lt</a>
+ * @version $Id: Constants.java,v 1.21 2006/03/05 02:43:19 herbyderby Exp $
+ */
+public interface Constants extends org.powermock.api.mockito.repackaged.asm.Opcodes {
+ public static final Class[] EMPTY_CLASS_ARRAY = {};
+ public static final Type[] TYPES_EMPTY = {};
+
+ public static final Signature SIG_STATIC =
+ TypeUtils.parseSignature("void <clinit>()");
+
+ public static final Type TYPE_OBJECT_ARRAY = TypeUtils.parseType("Object[]");
+ public static final Type TYPE_CLASS_ARRAY = TypeUtils.parseType("Class[]");
+ public static final Type TYPE_STRING_ARRAY = TypeUtils.parseType("String[]");
+
+ public static final Type TYPE_OBJECT = TypeUtils.parseType("Object");
+ public static final Type TYPE_CLASS = TypeUtils.parseType("Class");
+ public static final Type TYPE_CLASS_LOADER = TypeUtils.parseType("ClassLoader");
+ public static final Type TYPE_CHARACTER = TypeUtils.parseType("Character");
+ public static final Type TYPE_BOOLEAN = TypeUtils.parseType("Boolean");
+ public static final Type TYPE_DOUBLE = TypeUtils.parseType("Double");
+ public static final Type TYPE_FLOAT = TypeUtils.parseType("Float");
+ public static final Type TYPE_LONG = TypeUtils.parseType("Long");
+ public static final Type TYPE_INTEGER = TypeUtils.parseType("Integer");
+ public static final Type TYPE_SHORT = TypeUtils.parseType("Short");
+ public static final Type TYPE_BYTE = TypeUtils.parseType("Byte");
+ public static final Type TYPE_NUMBER = TypeUtils.parseType("Number");
+ public static final Type TYPE_STRING = TypeUtils.parseType("String");
+ public static final Type TYPE_THROWABLE = TypeUtils.parseType("Throwable");
+ public static final Type TYPE_BIG_INTEGER = TypeUtils.parseType("java.math.BigInteger");
+ public static final Type TYPE_BIG_DECIMAL = TypeUtils.parseType("java.math.BigDecimal");
+ public static final Type TYPE_STRING_BUFFER = TypeUtils.parseType("StringBuffer");
+ public static final Type TYPE_RUNTIME_EXCEPTION = TypeUtils.parseType("RuntimeException");
+ public static final Type TYPE_ERROR = TypeUtils.parseType("Error");
+ public static final Type TYPE_SYSTEM = TypeUtils.parseType("System");
+ public static final Type TYPE_SIGNATURE = TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.core.Signature");
+
+ public static final String CONSTRUCTOR_NAME = "<init>";
+ public static final String STATIC_NAME = "<clinit>";
+ public static final String SOURCE_FILE = "<generated>";
+ public static final String SUID_FIELD_NAME = "serialVersionUID";
+
+ public static final int PRIVATE_FINAL_STATIC = ACC_PRIVATE | ACC_FINAL | ACC_STATIC;
+
+ public static final int SWITCH_STYLE_TRIE = 0;
+ public static final int SWITCH_STYLE_HASH = 1;
+ public static final int SWITCH_STYLE_HASHONLY = 2;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Converter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Converter.java
new file mode 100644
index 0000000..5f9e9d4
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Converter.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+public interface Converter {
+ Object convert(Object value, Class target, Object context);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Customizer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Customizer.java
new file mode 100644
index 0000000..6fa1907
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Customizer.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+public interface Customizer {
+ void customize(CodeEmitter e, Type type);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DebuggingClassWriter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DebuggingClassWriter.java
new file mode 100644
index 0000000..1a9cc8f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DebuggingClassWriter.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassWriter;
+import org.powermock.api.mockito.repackaged.asm.util.TraceClassVisitor;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+public class DebuggingClassWriter extends ClassWriter {
+
+ public static final String DEBUG_LOCATION_PROPERTY = "cglib.debugLocation";
+
+ private static String debugLocation;
+ private static boolean traceEnabled;
+
+ static {
+ debugLocation = System.getProperty(DEBUG_LOCATION_PROPERTY);
+ if (debugLocation != null) {
+ System.err.println("CGLIB debugging enabled, writing to '" + debugLocation + "'");
+ try {
+ Class.forName("org.powermock.api.mockito.repackaged.asm.util.TraceClassVisitor");
+ traceEnabled = true;
+ } catch (Throwable ignore) {
+ }
+ }
+ }
+
+ private String className;
+ private String superName;
+
+ public DebuggingClassWriter(int flags) {
+ super(flags);
+ }
+
+ public void visit(int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ className = name.replace('/', '.');
+ this.superName = superName.replace('/', '.');
+ super.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ public String getClassName() {
+ return className;
+ }
+
+ public String getSuperName() {
+ return superName;
+ }
+
+ public byte[] toByteArray() {
+
+ return (byte[]) java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+
+
+ byte[] b = DebuggingClassWriter.super.toByteArray();
+ if (debugLocation != null) {
+ String dirs = className.replace('.', File.separatorChar);
+ try {
+ new File(debugLocation + File.separatorChar + dirs).getParentFile().mkdirs();
+
+ File file = new File(new File(debugLocation), dirs + ".class");
+ OutputStream out = new BufferedOutputStream(new FileOutputStream(file));
+ try {
+ out.write(b);
+ } finally {
+ out.close();
+ }
+
+ if (traceEnabled) {
+ file = new File(new File(debugLocation), dirs + ".asm");
+ out = new BufferedOutputStream(new FileOutputStream(file));
+ try {
+ ClassReader cr = new ClassReader(b);
+ PrintWriter pw = new PrintWriter(new OutputStreamWriter(out));
+ TraceClassVisitor tcv = new TraceClassVisitor(null, pw);
+ cr.accept(tcv, 0);
+ pw.flush();
+ } finally {
+ out.close();
+ }
+ }
+ } catch (IOException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+ return b;
+ }
+ });
+
+ }
+ }
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultGeneratorStrategy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultGeneratorStrategy.java
new file mode 100644
index 0000000..b503625
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultGeneratorStrategy.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassWriter;
+
+public class DefaultGeneratorStrategy implements GeneratorStrategy {
+ public static final DefaultGeneratorStrategy INSTANCE = new DefaultGeneratorStrategy();
+
+ public byte[] generate(ClassGenerator cg) throws Exception {
+ ClassWriter cw = getClassWriter();
+ transform(cg).generateClass(cw);
+ return transform(cw.toByteArray());
+ }
+
+ protected ClassWriter getClassWriter() throws Exception {
+ return new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
+ }
+
+ protected byte[] transform(byte[] b) throws Exception {
+ return b;
+ }
+
+ protected ClassGenerator transform(ClassGenerator cg) throws Exception {
+ return cg;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultNamingPolicy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultNamingPolicy.java
new file mode 100644
index 0000000..72fda07
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DefaultNamingPolicy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+/**
+ * The default policy used by {@link AbstractClassGenerator}.
+ * Generates names such as
+ * <p><code>org.powermock.api.mockito.repackaged.cglib.Foo$$EnhancerByCGLIB$$38272841</code><p>
+ * This is composed of a prefix based on the name of the superclass, a fixed
+ * string incorporating the CGLIB class responsible for generation, and a
+ * hashcode derived from the parameters used to create the object. If the same
+ * name has been previously been used in the same <code>ClassLoader</code>, a
+ * suffix is added to ensure uniqueness.
+ */
+public class DefaultNamingPolicy implements NamingPolicy {
+ public static final DefaultNamingPolicy INSTANCE = new DefaultNamingPolicy();
+
+ public String getClassName(String prefix, String source, Object key, Predicate names) {
+ if (prefix == null) {
+ prefix = "org.powermock.api.mockito.repackaged.cglib.empty.Object";
+ } else if (prefix.startsWith("java")) {
+ prefix = "$" + prefix;
+ }
+ String base =
+ prefix + "$$" +
+ source.substring(source.lastIndexOf('.') + 1) +
+ getTag() + "$$" +
+ Integer.toHexString(key.hashCode());
+ String attempt = base;
+ int index = 2;
+ while (names.evaluate(attempt))
+ attempt = base + "_" + index++;
+ return attempt;
+ }
+
+ /**
+ * Returns a string which is incorporated into every generated class name.
+ * By default returns "ByCGLIB"
+ */
+ protected String getTag() {
+ return "ByCGLIB";
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DuplicatesPredicate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DuplicatesPredicate.java
new file mode 100644
index 0000000..0148320
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/DuplicatesPredicate.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DuplicatesPredicate implements Predicate {
+ private Set unique = new HashSet();
+
+ public boolean evaluate(Object arg) {
+ return unique.add(MethodWrapper.create((Method)arg));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/EmitUtils.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/EmitUtils.java
new file mode 100644
index 0000000..1d052d0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/EmitUtils.java
@@ -0,0 +1,911 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class EmitUtils {
+ public static final ArrayDelimiters DEFAULT_DELIMITERS = new ArrayDelimiters("{", ", ", "}");
+ private static final Signature CSTRUCT_NULL =
+ TypeUtils.parseConstructor("");
+ private static final Signature CSTRUCT_THROWABLE =
+ TypeUtils.parseConstructor("Throwable");
+ private static final Signature GET_NAME =
+ TypeUtils.parseSignature("String getName()");
+ private static final Signature HASH_CODE =
+ TypeUtils.parseSignature("int hashCode()");
+ private static final Signature EQUALS =
+ TypeUtils.parseSignature("boolean equals(Object)");
+ private static final Signature STRING_LENGTH =
+ TypeUtils.parseSignature("int length()");
+ private static final Signature STRING_CHAR_AT =
+ TypeUtils.parseSignature("char charAt(int)");
+ private static final Signature FOR_NAME =
+ TypeUtils.parseSignature("Class forName(String)");
+ private static final Signature DOUBLE_TO_LONG_BITS =
+ TypeUtils.parseSignature("long doubleToLongBits(double)");
+ private static final Signature FLOAT_TO_INT_BITS =
+ TypeUtils.parseSignature("int floatToIntBits(float)");
+ private static final Signature TO_STRING =
+ TypeUtils.parseSignature("String toString()");
+ private static final Signature APPEND_STRING =
+ TypeUtils.parseSignature("StringBuffer append(String)");
+ private static final Signature APPEND_INT =
+ TypeUtils.parseSignature("StringBuffer append(int)");
+ private static final Signature APPEND_DOUBLE =
+ TypeUtils.parseSignature("StringBuffer append(double)");
+ private static final Signature APPEND_FLOAT =
+ TypeUtils.parseSignature("StringBuffer append(float)");
+ private static final Signature APPEND_CHAR =
+ TypeUtils.parseSignature("StringBuffer append(char)");
+ private static final Signature APPEND_LONG =
+ TypeUtils.parseSignature("StringBuffer append(long)");
+ private static final Signature APPEND_BOOLEAN =
+ TypeUtils.parseSignature("StringBuffer append(boolean)");
+ private static final Signature LENGTH =
+ TypeUtils.parseSignature("int length()");
+ private static final Signature SET_LENGTH =
+ TypeUtils.parseSignature("void setLength(int)");
+ private static final Signature GET_DECLARED_METHOD =
+ TypeUtils.parseSignature("java.lang.reflect.Method getDeclaredMethod(String, Class[])");
+
+ private EmitUtils() {
+ }
+
+ public static void factory_method(ClassEmitter ce, Signature sig) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, sig, null);
+ e.new_instance_this();
+ e.dup();
+ e.load_args();
+ e.invoke_constructor_this(TypeUtils.parseConstructor(sig.getArgumentTypes()));
+ e.return_value();
+ e.end_method();
+ }
+
+ public static void null_constructor(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, CSTRUCT_NULL, null);
+ e.load_this();
+ e.super_invoke_constructor();
+ e.return_value();
+ e.end_method();
+ }
+
+ /**
+ * Process an array on the stack. Assumes the top item on the stack
+ * is an array of the specified type. For each element in the array,
+ * puts the element on the stack and triggers the callback.
+ * @param type the type of the array (type.isArray() must be true)
+ * @param callback the callback triggered for each element
+ */
+ public static void process_array(CodeEmitter e, Type type, ProcessArrayCallback callback) {
+ Type componentType = TypeUtils.getComponentType(type);
+ Local array = e.make_local();
+ Local loopvar = e.make_local(Type.INT_TYPE);
+ Label loopbody = e.make_label();
+ Label checkloop = e.make_label();
+ e.store_local(array);
+ e.push(0);
+ e.store_local(loopvar);
+ e.goTo(checkloop);
+
+ e.mark(loopbody);
+ e.load_local(array);
+ e.load_local(loopvar);
+ e.array_load(componentType);
+ callback.processElement(componentType);
+ e.iinc(loopvar, 1);
+
+ e.mark(checkloop);
+ e.load_local(loopvar);
+ e.load_local(array);
+ e.arraylength();
+ e.if_icmp(e.LT, loopbody);
+ }
+
+ /**
+ * Process two arrays on the stack in parallel. Assumes the top two items on the stack
+ * are arrays of the specified class. The arrays must be the same length. For each pair
+ * of elements in the arrays, puts the pair on the stack and triggers the callback.
+ * @param type the type of the arrays (type.isArray() must be true)
+ * @param callback the callback triggered for each pair of elements
+ */
+ public static void process_arrays(CodeEmitter e, Type type, ProcessArrayCallback callback) {
+ Type componentType = TypeUtils.getComponentType(type);
+ Local array1 = e.make_local();
+ Local array2 = e.make_local();
+ Local loopvar = e.make_local(Type.INT_TYPE);
+ Label loopbody = e.make_label();
+ Label checkloop = e.make_label();
+ e.store_local(array1);
+ e.store_local(array2);
+ e.push(0);
+ e.store_local(loopvar);
+ e.goTo(checkloop);
+
+ e.mark(loopbody);
+ e.load_local(array1);
+ e.load_local(loopvar);
+ e.array_load(componentType);
+ e.load_local(array2);
+ e.load_local(loopvar);
+ e.array_load(componentType);
+ callback.processElement(componentType);
+ e.iinc(loopvar, 1);
+
+ e.mark(checkloop);
+ e.load_local(loopvar);
+ e.load_local(array1);
+ e.arraylength();
+ e.if_icmp(e.LT, loopbody);
+ }
+
+ public static void string_switch(CodeEmitter e, String[] strings, int switchStyle, ObjectSwitchCallback callback) {
+ try {
+ switch (switchStyle) {
+ case Constants.SWITCH_STYLE_TRIE:
+ string_switch_trie(e, strings, callback);
+ break;
+ case Constants.SWITCH_STYLE_HASH:
+ string_switch_hash(e, strings, callback, false);
+ break;
+ case Constants.SWITCH_STYLE_HASHONLY:
+ string_switch_hash(e, strings, callback, true);
+ break;
+ default:
+ throw new IllegalArgumentException("unknown switch style " + switchStyle);
+ }
+ } catch (RuntimeException ex) {
+ throw ex;
+ } catch (Error ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new CodeGenerationException(ex);
+ }
+ }
+
+ private static void string_switch_trie(final CodeEmitter e,
+ String[] strings,
+ final ObjectSwitchCallback callback) throws Exception {
+ final Label def = e.make_label();
+ final Label end = e.make_label();
+ final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() {
+ public Object transform(Object value) {
+ return new Integer(((String)value).length());
+ }
+ });
+ e.dup();
+ e.invoke_virtual(Constants.TYPE_STRING, STRING_LENGTH);
+ e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
+ public void processCase(int key, Label ignore_end) throws Exception {
+ List bucket = (List)buckets.get(new Integer(key));
+ stringSwitchHelper(e, bucket, callback, def, end, 0);
+ }
+ public void processDefault() {
+ e.goTo(def);
+ }
+ });
+ e.mark(def);
+ e.pop();
+ callback.processDefault();
+ e.mark(end);
+ }
+
+ private static void stringSwitchHelper(final CodeEmitter e,
+ List strings,
+ final ObjectSwitchCallback callback,
+ final Label def,
+ final Label end,
+ final int index) throws Exception {
+ final int len = ((String)strings.get(0)).length();
+ final Map buckets = CollectionUtils.bucket(strings, new Transformer() {
+ public Object transform(Object value) {
+ return new Integer(((String)value).charAt(index));
+ }
+ });
+ e.dup();
+ e.push(index);
+ e.invoke_virtual(Constants.TYPE_STRING, STRING_CHAR_AT);
+ e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
+ public void processCase(int key, Label ignore_end) throws Exception {
+ List bucket = (List)buckets.get(new Integer(key));
+ if (index + 1 == len) {
+ e.pop();
+ callback.processCase(bucket.get(0), end);
+ } else {
+ stringSwitchHelper(e, bucket, callback, def, end, index + 1);
+ }
+ }
+ public void processDefault() {
+ e.goTo(def);
+ }
+ });
+ }
+
+ static int[] getSwitchKeys(Map buckets) {
+ int[] keys = new int[buckets.size()];
+ int index = 0;
+ for (Iterator it = buckets.keySet().iterator(); it.hasNext();) {
+ keys[index++] = ((Integer)it.next()).intValue();
+ }
+ Arrays.sort(keys);
+ return keys;
+ }
+
+ private static void string_switch_hash(final CodeEmitter e,
+ final String[] strings,
+ final ObjectSwitchCallback callback,
+ final boolean skipEquals) throws Exception {
+ final Map buckets = CollectionUtils.bucket(Arrays.asList(strings), new Transformer() {
+ public Object transform(Object value) {
+ return new Integer(value.hashCode());
+ }
+ });
+ final Label def = e.make_label();
+ final Label end = e.make_label();
+ e.dup();
+ e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE);
+ e.process_switch(getSwitchKeys(buckets), new ProcessSwitchCallback() {
+ public void processCase(int key, Label ignore_end) throws Exception {
+ List bucket = (List)buckets.get(new Integer(key));
+ Label next = null;
+ if (skipEquals && bucket.size() == 1) {
+ if (skipEquals)
+ e.pop();
+ callback.processCase((String)bucket.get(0), end);
+ } else {
+ for (Iterator it = bucket.iterator(); it.hasNext();) {
+ String string = (String)it.next();
+ if (next != null) {
+ e.mark(next);
+ }
+ if (it.hasNext()) {
+ e.dup();
+ }
+ e.push(string);
+ e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
+ if (it.hasNext()) {
+ e.if_jump(e.EQ, next = e.make_label());
+ e.pop();
+ } else {
+ e.if_jump(e.EQ, def);
+ }
+ callback.processCase(string, end);
+ }
+ }
+ }
+ public void processDefault() {
+ e.pop();
+ }
+ });
+ e.mark(def);
+ callback.processDefault();
+ e.mark(end);
+ }
+
+ public static void load_class_this(CodeEmitter e) {
+ load_class_helper(e, e.getClassEmitter().getClassType());
+ }
+
+ public static void load_class(CodeEmitter e, Type type) {
+ if (TypeUtils.isPrimitive(type)) {
+ if (type == Type.VOID_TYPE) {
+ throw new IllegalArgumentException("cannot load void type");
+ }
+ e.getstatic(TypeUtils.getBoxedType(type), "TYPE", Constants.TYPE_CLASS);
+ } else {
+ load_class_helper(e, type);
+ }
+ }
+
+ private static void load_class_helper(CodeEmitter e, final Type type) {
+ if (e.isStaticHook()) {
+ // have to fall back on non-optimized load
+ e.push(TypeUtils.emulateClassGetName(type));
+ e.invoke_static(Constants.TYPE_CLASS, FOR_NAME);
+ } else {
+ ClassEmitter ce = e.getClassEmitter();
+ String typeName = TypeUtils.emulateClassGetName(type);
+
+ // TODO: can end up with duplicated field names when using chained transformers; incorporate static hook # somehow
+ String fieldName = "CGLIB$load_class$" + TypeUtils.escapeType(typeName);
+ if (!ce.isFieldDeclared(fieldName)) {
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, fieldName, Constants.TYPE_CLASS, null);
+ CodeEmitter hook = ce.getStaticHook();
+ hook.push(typeName);
+ hook.invoke_static(Constants.TYPE_CLASS, FOR_NAME);
+ hook.putstatic(ce.getClassType(), fieldName, Constants.TYPE_CLASS);
+ }
+ e.getfield(fieldName);
+ }
+ }
+
+ public static void push_array(CodeEmitter e, Object[] array) {
+ e.push(array.length);
+ e.newarray(Type.getType(remapComponentType(array.getClass().getComponentType())));
+ for (int i = 0; i < array.length; i++) {
+ e.dup();
+ e.push(i);
+ push_object(e, array[i]);
+ e.aastore();
+ }
+ }
+
+ private static Class remapComponentType(Class componentType) {
+ if (componentType.equals(Type.class))
+ return Class.class;
+ return componentType;
+ }
+
+ public static void push_object(CodeEmitter e, Object obj) {
+ if (obj == null) {
+ e.aconst_null();
+ } else {
+ Class type = obj.getClass();
+ if (type.isArray()) {
+ push_array(e, (Object[])obj);
+ } else if (obj instanceof String) {
+ e.push((String)obj);
+ } else if (obj instanceof Type) {
+ load_class(e, (Type)obj);
+ } else if (obj instanceof Class) {
+ load_class(e, Type.getType((Class)obj));
+ } else if (obj instanceof BigInteger) {
+ e.new_instance(Constants.TYPE_BIG_INTEGER);
+ e.dup();
+ e.push(obj.toString());
+ e.invoke_constructor(Constants.TYPE_BIG_INTEGER);
+ } else if (obj instanceof BigDecimal) {
+ e.new_instance(Constants.TYPE_BIG_DECIMAL);
+ e.dup();
+ e.push(obj.toString());
+ e.invoke_constructor(Constants.TYPE_BIG_DECIMAL);
+ } else {
+ throw new IllegalArgumentException("unknown type: " + obj.getClass());
+ }
+ }
+ }
+
+ public static void hash_code(CodeEmitter e, Type type, int multiplier, Customizer customizer) {
+ if (TypeUtils.isArray(type)) {
+ hash_array(e, type, multiplier, customizer);
+ } else {
+ e.swap(Type.INT_TYPE, type);
+ e.push(multiplier);
+ e.math(e.MUL, Type.INT_TYPE);
+ e.swap(type, Type.INT_TYPE);
+ if (TypeUtils.isPrimitive(type)) {
+ hash_primitive(e, type);
+ } else {
+ hash_object(e, type, customizer);
+ }
+ e.math(e.ADD, Type.INT_TYPE);
+ }
+ }
+
+ private static void hash_array(final CodeEmitter e, Type type, final int multiplier, final Customizer customizer) {
+ Label skip = e.make_label();
+ Label end = e.make_label();
+ e.dup();
+ e.ifnull(skip);
+ EmitUtils.process_array(e, type, new ProcessArrayCallback() {
+ public void processElement(Type type) {
+ hash_code(e, type, multiplier, customizer);
+ }
+ });
+ e.goTo(end);
+ e.mark(skip);
+ e.pop();
+ e.mark(end);
+ }
+
+ private static void hash_object(CodeEmitter e, Type type, Customizer customizer) {
+ // (f == null) ? 0 : f.hashCode();
+ Label skip = e.make_label();
+ Label end = e.make_label();
+ e.dup();
+ e.ifnull(skip);
+ if (customizer != null) {
+ customizer.customize(e, type);
+ }
+ e.invoke_virtual(Constants.TYPE_OBJECT, HASH_CODE);
+ e.goTo(end);
+ e.mark(skip);
+ e.pop();
+ e.push(0);
+ e.mark(end);
+ }
+
+ private static void hash_primitive(CodeEmitter e, Type type) {
+ switch (type.getSort()) {
+ case Type.BOOLEAN:
+ // f ? 0 : 1
+ e.push(1);
+ e.math(e.XOR, Type.INT_TYPE);
+ break;
+ case Type.FLOAT:
+ // Float.floatToIntBits(f)
+ e.invoke_static(Constants.TYPE_FLOAT, FLOAT_TO_INT_BITS);
+ break;
+ case Type.DOUBLE:
+ // Double.doubleToLongBits(f), hash_code(Long.TYPE)
+ e.invoke_static(Constants.TYPE_DOUBLE, DOUBLE_TO_LONG_BITS);
+ // fall through
+ case Type.LONG:
+ hash_long(e);
+ }
+ }
+
+ private static void hash_long(CodeEmitter e) {
+ // (int)(f ^ (f >>> 32))
+ e.dup2();
+ e.push(32);
+ e.math(e.USHR, Type.LONG_TYPE);
+ e.math(e.XOR, Type.LONG_TYPE);
+ e.cast_numeric(Type.LONG_TYPE, Type.INT_TYPE);
+ }
+
+// public static void not_equals(CodeEmitter e, Type type, Label notEquals) {
+// not_equals(e, type, notEquals, null);
+// }
+
+ /**
+ * Branches to the specified label if the top two items on the stack
+ * are not equal. The items must both be of the specified
+ * class. Equality is determined by comparing primitive values
+ * directly and by invoking the <code>equals</code> method for
+ * Objects. Arrays are recursively processed in the same manner.
+ */
+ public static void not_equals(final CodeEmitter e, Type type, final Label notEquals, final Customizer customizer) {
+ (new ProcessArrayCallback() {
+ public void processElement(Type type) {
+ not_equals_helper(e, type, notEquals, customizer, this);
+ }
+ }).processElement(type);
+ }
+
+ private static void not_equals_helper(CodeEmitter e,
+ Type type,
+ Label notEquals,
+ Customizer customizer,
+ ProcessArrayCallback callback) {
+ if (TypeUtils.isPrimitive(type)) {
+ e.if_cmp(type, e.NE, notEquals);
+ } else {
+ Label end = e.make_label();
+ nullcmp(e, notEquals, end);
+ if (TypeUtils.isArray(type)) {
+ Label checkContents = e.make_label();
+ e.dup2();
+ e.arraylength();
+ e.swap();
+ e.arraylength();
+ e.if_icmp(e.EQ, checkContents);
+ e.pop2();
+ e.goTo(notEquals);
+ e.mark(checkContents);
+ EmitUtils.process_arrays(e, type, callback);
+ } else {
+ if (customizer != null) {
+ customizer.customize(e, type);
+ e.swap();
+ customizer.customize(e, type);
+ }
+ e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
+ e.if_jump(e.EQ, notEquals);
+ }
+ e.mark(end);
+ }
+ }
+
+ /**
+ * If both objects on the top of the stack are non-null, does nothing.
+ * If one is null, or both are null, both are popped off and execution
+ * branches to the respective label.
+ * @param oneNull label to branch to if only one of the objects is null
+ * @param bothNull label to branch to if both of the objects are null
+ */
+ private static void nullcmp(CodeEmitter e, Label oneNull, Label bothNull) {
+ e.dup2();
+ Label nonNull = e.make_label();
+ Label oneNullHelper = e.make_label();
+ Label end = e.make_label();
+ e.ifnonnull(nonNull);
+ e.ifnonnull(oneNullHelper);
+ e.pop2();
+ e.goTo(bothNull);
+
+ e.mark(nonNull);
+ e.ifnull(oneNullHelper);
+ e.goTo(end);
+
+ e.mark(oneNullHelper);
+ e.pop2();
+ e.goTo(oneNull);
+
+ e.mark(end);
+ }
+
+ /*
+ public static void to_string(CodeEmitter e,
+ Type type,
+ ArrayDelimiters delims,
+ Customizer customizer) {
+ e.new_instance(Constants.TYPE_STRING_BUFFER);
+ e.dup();
+ e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
+ e.swap();
+ append_string(e, type, delims, customizer);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
+ }
+ */
+
+ public static void append_string(final CodeEmitter e,
+ Type type,
+ final ArrayDelimiters delims,
+ final Customizer customizer) {
+ final ArrayDelimiters d = (delims != null) ? delims : DEFAULT_DELIMITERS;
+ ProcessArrayCallback callback = new ProcessArrayCallback() {
+ public void processElement(Type type) {
+ append_string_helper(e, type, d, customizer, this);
+ e.push(d.inside);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ }
+ };
+ append_string_helper(e, type, d, customizer, callback);
+ }
+
+ private static void append_string_helper(CodeEmitter e,
+ Type type,
+ ArrayDelimiters delims,
+ Customizer customizer,
+ ProcessArrayCallback callback) {
+ Label skip = e.make_label();
+ Label end = e.make_label();
+ if (TypeUtils.isPrimitive(type)) {
+ switch (type.getSort()) {
+ case Type.INT:
+ case Type.SHORT:
+ case Type.BYTE:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_INT);
+ break;
+ case Type.DOUBLE:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_DOUBLE);
+ break;
+ case Type.FLOAT:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_FLOAT);
+ break;
+ case Type.LONG:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_LONG);
+ break;
+ case Type.BOOLEAN:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_BOOLEAN);
+ break;
+ case Type.CHAR:
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_CHAR);
+ break;
+ }
+ } else if (TypeUtils.isArray(type)) {
+ e.dup();
+ e.ifnull(skip);
+ e.swap();
+ if (delims != null && delims.before != null && !"".equals(delims.before)) {
+ e.push(delims.before);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ e.swap();
+ }
+ EmitUtils.process_array(e, type, callback);
+ shrinkStringBuffer(e, 2);
+ if (delims != null && delims.after != null && !"".equals(delims.after)) {
+ e.push(delims.after);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ }
+ } else {
+ e.dup();
+ e.ifnull(skip);
+ if (customizer != null) {
+ customizer.customize(e, type);
+ }
+ e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ }
+ e.goTo(end);
+ e.mark(skip);
+ e.pop();
+ e.push("null");
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ e.mark(end);
+ }
+
+ private static void shrinkStringBuffer(CodeEmitter e, int amt) {
+ e.dup();
+ e.dup();
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, LENGTH);
+ e.push(amt);
+ e.math(e.SUB, Type.INT_TYPE);
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, SET_LENGTH);
+ }
+
+ public static void load_method(CodeEmitter e, MethodInfo method) {
+ load_class(e, method.getClassInfo().getType());
+ e.push(method.getSignature().getName());
+ push_object(e, method.getSignature().getArgumentTypes());
+ e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHOD);
+ }
+
+ public static void method_switch(CodeEmitter e,
+ List methods,
+ ObjectSwitchCallback callback) {
+ member_switch_helper(e, methods, callback, true);
+ }
+
+ public static void constructor_switch(CodeEmitter e,
+ List constructors,
+ ObjectSwitchCallback callback) {
+ member_switch_helper(e, constructors, callback, false);
+ }
+
+ private static void member_switch_helper(final CodeEmitter e,
+ List members,
+ final ObjectSwitchCallback callback,
+ boolean useName) {
+ try {
+ final Map cache = new HashMap();
+ final ParameterTyper cached = new ParameterTyper() {
+ public Type[] getParameterTypes(MethodInfo member) {
+ Type[] types = (Type[])cache.get(member);
+ if (types == null) {
+ cache.put(member, types = member.getSignature().getArgumentTypes());
+ }
+ return types;
+ }
+ };
+ final Label def = e.make_label();
+ final Label end = e.make_label();
+ if (useName) {
+ e.swap();
+ final Map buckets = CollectionUtils.bucket(members, new Transformer() {
+ public Object transform(Object value) {
+ return ((MethodInfo)value).getSignature().getName();
+ }
+ });
+ String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]);
+ EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label dontUseEnd) throws Exception {
+ member_helper_size(e, (List)buckets.get(key), callback, cached, def, end);
+ }
+ public void processDefault() throws Exception {
+ e.goTo(def);
+ }
+ });
+ } else {
+ member_helper_size(e, members, callback, cached, def, end);
+ }
+ e.mark(def);
+ e.pop();
+ callback.processDefault();
+ e.mark(end);
+ } catch (RuntimeException ex) {
+ throw ex;
+ } catch (Error ex) {
+ throw ex;
+ } catch (Exception ex) {
+ throw new CodeGenerationException(ex);
+ }
+ }
+
+ private static void member_helper_size(final CodeEmitter e,
+ List members,
+ final ObjectSwitchCallback callback,
+ final ParameterTyper typer,
+ final Label def,
+ final Label end) throws Exception {
+ final Map buckets = CollectionUtils.bucket(members, new Transformer() {
+ public Object transform(Object value) {
+ return new Integer(typer.getParameterTypes((MethodInfo)value).length);
+ }
+ });
+ e.dup();
+ e.arraylength();
+ e.process_switch(EmitUtils.getSwitchKeys(buckets), new ProcessSwitchCallback() {
+ public void processCase(int key, Label dontUseEnd) throws Exception {
+ List bucket = (List)buckets.get(new Integer(key));
+ member_helper_type(e, bucket, callback, typer, def, end, new BitSet());
+ }
+ public void processDefault() throws Exception {
+ e.goTo(def);
+ }
+ });
+ }
+
+ private static void member_helper_type(final CodeEmitter e,
+ List members,
+ final ObjectSwitchCallback callback,
+ final ParameterTyper typer,
+ final Label def,
+ final Label end,
+ final BitSet checked) throws Exception {
+ if (members.size() == 1) {
+ MethodInfo member = (MethodInfo)members.get(0);
+ Type[] types = typer.getParameterTypes(member);
+ // need to check classes that have not already been checked via switches
+ for (int i = 0; i < types.length; i++) {
+ if (checked == null || !checked.get(i)) {
+ e.dup();
+ e.aaload(i);
+ e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
+ e.push(TypeUtils.emulateClassGetName(types[i]));
+ e.invoke_virtual(Constants.TYPE_OBJECT, EQUALS);
+ e.if_jump(e.EQ, def);
+ }
+ }
+ e.pop();
+ callback.processCase(member, end);
+ } else {
+ // choose the index that has the best chance of uniquely identifying member
+ Type[] example = typer.getParameterTypes((MethodInfo)members.get(0));
+ Map buckets = null;
+ int index = -1;
+ for (int i = 0; i < example.length; i++) {
+ final int j = i;
+ Map test = CollectionUtils.bucket(members, new Transformer() {
+ public Object transform(Object value) {
+ return TypeUtils.emulateClassGetName(typer.getParameterTypes((MethodInfo)value)[j]);
+ }
+ });
+ if (buckets == null || test.size() > buckets.size()) {
+ buckets = test;
+ index = i;
+ }
+ }
+ if (buckets == null || buckets.size() == 1) {
+ // TODO: switch by returnType
+ // must have two methods with same name, types, and different return types
+ e.goTo(def);
+ } else {
+ checked.set(index);
+
+ e.dup();
+ e.aaload(index);
+ e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
+
+ final Map fbuckets = buckets;
+ String[] names = (String[])buckets.keySet().toArray(new String[buckets.size()]);
+ EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label dontUseEnd) throws Exception {
+ member_helper_type(e, (List)fbuckets.get(key), callback, typer, def, end, checked);
+ }
+ public void processDefault() throws Exception {
+ e.goTo(def);
+ }
+ });
+ }
+ }
+ }
+
+ public static void wrap_throwable(Block block, Type wrapper) {
+ CodeEmitter e = block.getCodeEmitter();
+ e.catch_exception(block, Constants.TYPE_THROWABLE);
+ e.new_instance(wrapper);
+ e.dup_x1();
+ e.swap();
+ e.invoke_constructor(wrapper, CSTRUCT_THROWABLE);
+ e.athrow();
+ }
+
+ public static void add_properties(ClassEmitter ce, String[] names, Type[] types) {
+ for (int i = 0; i < names.length; i++) {
+ String fieldName = "$cglib_prop_" + names[i];
+ ce.declare_field(Constants.ACC_PRIVATE, fieldName, types[i], null);
+ EmitUtils.add_property(ce, names[i], types[i], fieldName);
+ }
+ }
+
+ public static void add_property(ClassEmitter ce, String name, Type type, String fieldName) {
+ String property = TypeUtils.upperFirst(name);
+ CodeEmitter e;
+ e = ce.begin_method(Constants.ACC_PUBLIC,
+ new Signature("get" + property,
+ type,
+ Constants.TYPES_EMPTY),
+ null);
+ e.load_this();
+ e.getfield(fieldName);
+ e.return_value();
+ e.end_method();
+
+ e = ce.begin_method(Constants.ACC_PUBLIC,
+ new Signature("set" + property,
+ Type.VOID_TYPE,
+ new Type[]{ type }),
+ null);
+ e.load_this();
+ e.load_arg(0);
+ e.putfield(fieldName);
+ e.return_value();
+ e.end_method();
+ }
+
+ /* generates:
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Error e) {
+ throw e;
+ } catch (<DeclaredException> e) {
+ throw e;
+ } catch (Throwable e) {
+ throw new <Wrapper>(e);
+ }
+ */
+ public static void wrap_undeclared_throwable(CodeEmitter e, Block handler, Type[] exceptions, Type wrapper) {
+ Set set = (exceptions == null) ? Collections.EMPTY_SET : new HashSet(Arrays.asList(exceptions));
+
+ if (set.contains(Constants.TYPE_THROWABLE))
+ return;
+
+ boolean needThrow = exceptions != null;
+ if (!set.contains(Constants.TYPE_RUNTIME_EXCEPTION)) {
+ e.catch_exception(handler, Constants.TYPE_RUNTIME_EXCEPTION);
+ needThrow = true;
+ }
+ if (!set.contains(Constants.TYPE_ERROR)) {
+ e.catch_exception(handler, Constants.TYPE_ERROR);
+ needThrow = true;
+ }
+ if (exceptions != null) {
+ for (int i = 0; i < exceptions.length; i++) {
+ e.catch_exception(handler, exceptions[i]);
+ }
+ }
+ if (needThrow) {
+ e.athrow();
+ }
+ // e -> eo -> oeo -> ooe -> o
+ e.catch_exception(handler, Constants.TYPE_THROWABLE);
+ e.new_instance(wrapper);
+ e.dup_x1();
+ e.swap();
+ e.invoke_constructor(wrapper, CSTRUCT_THROWABLE);
+ e.athrow();
+ }
+
+ public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method) {
+ return begin_method(e, method, method.getModifiers());
+ }
+
+ public static CodeEmitter begin_method(ClassEmitter e, MethodInfo method, int access) {
+ return e.begin_method(access,
+ method.getSignature(),
+ method.getExceptionTypes());
+ }
+
+ private interface ParameterTyper {
+ Type[] getParameterTypes(MethodInfo member);
+ }
+
+ public static class ArrayDelimiters {
+ private String before;
+ private String inside;
+ private String after;
+
+ public ArrayDelimiters(String before, String inside, String after) {
+ this.before = before;
+ this.inside = inside;
+ this.after = after;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/GeneratorStrategy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/GeneratorStrategy.java
new file mode 100644
index 0000000..2c82a9c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/GeneratorStrategy.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+/**
+ * The <code>GeneratorStrategy</code. is responsible for taking a
+ * {@link ClassGenerator} and producing a byte array containing the
+ * data for the generated <code>Class</code>. By providing your
+ * own strategy you may examine or modify the generated class before
+ * it is loaded. Typically this will be accomplished by subclassing
+ * {@link DefaultGeneratorStrategy} and overriding the appropriate
+ * protected method.
+ * @see AbstractClassGenerator#setStrategy
+ */
+public interface GeneratorStrategy {
+ /**
+ * Generate the class.
+ * @param cg a class generator on which you can call {@link ClassGenerator#generateClass}
+ * @return a byte array containing the bits of a valid Class
+ */
+ byte[] generate(ClassGenerator cg) throws Exception;
+
+ /**
+ * The <code>GeneratorStrategy</code> in use does not currently, but may
+ * in the future, affect the caching of classes generated by {@link
+ * AbstractClassGenerator}, so this is a reminder that you should
+ * correctly implement <code>equals</code> and <code>hashCode</code>
+ * to avoid generating too many classes.
+ */
+ boolean equals(Object o);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/KeyFactory.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/KeyFactory.java
new file mode 100644
index 0000000..cac12e0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/KeyFactory.java
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.lang.reflect.Method;
+
+/**
+ * Generates classes to handle multi-valued keys, for use in things such as Maps and Sets.
+ * Code for <code>equals</code> and <code>hashCode</code> methods follow the
+ * the rules laid out in <i>Effective Java</i> by Joshua Bloch.
+ * <p>
+ * To generate a <code>KeyFactory</code>, you need to supply an interface which
+ * describes the structure of the key. The interface should have a
+ * single method named <code>newInstance</code>, which returns an
+ * <code>Object</code>. The arguments array can be
+ * <i>anything</i>--Objects, primitive values, or single or
+ * multi-dimension arrays of either. For example:
+ * <p><pre>
+ * private interface IntStringKey {
+ * public Object newInstance(int i, String s);
+ * }
+ * </pre><p>
+ * Once you have made a <code>KeyFactory</code>, you generate a new key by calling
+ * the <code>newInstance</code> method defined by your interface.
+ * <p><pre>
+ * IntStringKey factory = (IntStringKey)KeyFactory.create(IntStringKey.class);
+ * Object key1 = factory.newInstance(4, "Hello");
+ * Object key2 = factory.newInstance(4, "World");
+ * </pre><p>
+ * <b>Note:</b>
+ * <code>hashCode</code> equality between two keys <code>key1</code> and <code>key2</code> is only guaranteed if
+ * <code>key1.equals(key2)</code> <i>and</i> the keys were produced by the same factory.
+ *
+ * @version $Id: KeyFactory.java,v 1.26 2006/03/05 02:43:19 herbyderby Exp $
+ */
+abstract public class KeyFactory {
+ private static final Signature GET_NAME =
+ TypeUtils.parseSignature("String getName()");
+ public static final Customizer CLASS_BY_NAME = new Customizer() {
+ public void customize(CodeEmitter e, Type type) {
+ if (type.equals(Constants.TYPE_CLASS)) {
+ e.invoke_virtual(Constants.TYPE_CLASS, GET_NAME);
+ }
+ }
+ };
+ private static final Signature GET_CLASS =
+ TypeUtils.parseSignature("Class getClass()");
+ public static final Customizer OBJECT_BY_CLASS = new Customizer() {
+ public void customize(CodeEmitter e, Type type) {
+ e.invoke_virtual(Constants.TYPE_OBJECT, GET_CLASS);
+ }
+ };
+ private static final Signature HASH_CODE =
+ TypeUtils.parseSignature("int hashCode()");
+ private static final Signature EQUALS =
+ TypeUtils.parseSignature("boolean equals(Object)");
+ private static final Signature TO_STRING =
+ TypeUtils.parseSignature("String toString()");
+ private static final Signature APPEND_STRING =
+ TypeUtils.parseSignature("StringBuffer append(String)");
+ private static final Type KEY_FACTORY =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.core.KeyFactory");
+ //generated numbers:
+ private final static int PRIMES[] = {
+ 11, 73, 179, 331,
+ 521, 787, 1213, 1823,
+ 2609, 3691, 5189, 7247,
+ 10037, 13931, 19289, 26627,
+ 36683, 50441, 69403, 95401,
+ 131129, 180179, 247501, 340057,
+ 467063, 641371, 880603, 1209107,
+ 1660097, 2279161, 3129011, 4295723,
+ 5897291, 8095873, 11114263, 15257791,
+ 20946017, 28754629, 39474179, 54189869,
+ 74391461, 102123817, 140194277, 192456917,
+ 264202273, 362693231, 497900099, 683510293,
+ 938313161, 1288102441, 1768288259 };
+
+ protected KeyFactory() {
+ }
+
+ public static KeyFactory create(Class keyInterface) {
+ return create(keyInterface, null);
+ }
+
+ public static KeyFactory create(Class keyInterface, Customizer customizer) {
+ return create(keyInterface.getClassLoader(), keyInterface, customizer);
+ }
+
+ public static KeyFactory create(ClassLoader loader, Class keyInterface, Customizer customizer) {
+ Generator gen = new Generator();
+ gen.setInterface(keyInterface);
+ gen.setCustomizer(customizer);
+ gen.setClassLoader(loader);
+ return gen.create();
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(KeyFactory.class.getName());
+ private Class keyInterface;
+ private Customizer customizer;
+ private int constant;
+ private int multiplier;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return keyInterface.getClassLoader();
+ }
+
+ public void setCustomizer(Customizer customizer) {
+ this.customizer = customizer;
+ }
+
+ public void setInterface(Class keyInterface) {
+ this.keyInterface = keyInterface;
+ }
+
+ public KeyFactory create() {
+ setNamePrefix(keyInterface.getName());
+ return (KeyFactory)super.create(keyInterface.getName());
+ }
+
+ public void setHashConstant(int constant) {
+ this.constant = constant;
+ }
+
+ public void setHashMultiplier(int multiplier) {
+ this.multiplier = multiplier;
+ }
+
+ protected Object firstInstance(Class type) {
+ return ReflectUtils.newInstance(type);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+
+ public void generateClass(ClassVisitor v) {
+ ClassEmitter ce = new ClassEmitter(v);
+
+ Method newInstance = ReflectUtils.findNewInstance(keyInterface);
+ if (!newInstance.getReturnType().equals(Object.class)) {
+ throw new IllegalArgumentException("newInstance method must return Object");
+ }
+
+ Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ KEY_FACTORY,
+ new Type[]{ Type.getType(keyInterface) },
+ Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(ce);
+ EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));
+
+ int seed = 0;
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
+ TypeUtils.parseConstructor(parameterTypes),
+ null);
+ e.load_this();
+ e.super_invoke_constructor();
+ e.load_this();
+ for (int i = 0; i < parameterTypes.length; i++) {
+ seed += parameterTypes[i].hashCode();
+ ce.declare_field(Constants.ACC_PRIVATE | Constants.ACC_FINAL,
+ getFieldName(i),
+ parameterTypes[i],
+ null);
+ e.dup();
+ e.load_arg(i);
+ e.putfield(getFieldName(i));
+ }
+ e.return_value();
+ e.end_method();
+
+ // hash code
+ e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
+ int hc = (constant != 0) ? constant : PRIMES[(int)(Math.abs(seed) % PRIMES.length)];
+ int hm = (multiplier != 0) ? multiplier : PRIMES[(int)(Math.abs(seed * 13) % PRIMES.length)];
+ e.push(hc);
+ for (int i = 0; i < parameterTypes.length; i++) {
+ e.load_this();
+ e.getfield(getFieldName(i));
+ EmitUtils.hash_code(e, parameterTypes[i], hm, customizer);
+ }
+ e.return_value();
+ e.end_method();
+
+ // equals
+ e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
+ Label fail = e.make_label();
+ e.load_arg(0);
+ e.instance_of_this();
+ e.if_jump(e.EQ, fail);
+ for (int i = 0; i < parameterTypes.length; i++) {
+ e.load_this();
+ e.getfield(getFieldName(i));
+ e.load_arg(0);
+ e.checkcast_this();
+ e.getfield(getFieldName(i));
+ EmitUtils.not_equals(e, parameterTypes[i], fail, customizer);
+ }
+ e.push(1);
+ e.return_value();
+ e.mark(fail);
+ e.push(0);
+ e.return_value();
+ e.end_method();
+
+ // toString
+ e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
+ e.new_instance(Constants.TYPE_STRING_BUFFER);
+ e.dup();
+ e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
+ for (int i = 0; i < parameterTypes.length; i++) {
+ if (i > 0) {
+ e.push(", ");
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
+ }
+ e.load_this();
+ e.getfield(getFieldName(i));
+ EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizer);
+ }
+ e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
+ e.return_value();
+ e.end_method();
+
+ ce.end_class();
+ }
+
+ private String getFieldName(int arg) {
+ return "FIELD_" + arg;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Local.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Local.java
new file mode 100644
index 0000000..026024f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Local.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+public class Local
+{
+ private Type type;
+ private int index;
+
+ public Local(int index, Type type) {
+ this.type = type;
+ this.index = index;
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ public Type getType() {
+ return type;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/LocalVariablesSorter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/LocalVariablesSorter.java
new file mode 100644
index 0000000..af4b4fd
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/LocalVariablesSorter.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodAdapter;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+import org.powermock.api.mockito.repackaged.asm.Opcodes;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * A {@link MethodAdapter} that renumbers local variables in their order of
+ * appearance. This adapter allows one to easily add new local variables to a
+ * method.
+ *
+ * @author Chris Nokleberg
+ * @author Eric Bruneton
+ */
+public class LocalVariablesSorter extends MethodAdapter {
+
+ protected final int firstLocal;
+ private final State state;
+ public LocalVariablesSorter(
+ final int access,
+ final String desc,
+ final MethodVisitor mv)
+ {
+ super(mv);
+ state = new State();
+ Type[] args = Type.getArgumentTypes(desc);
+ state.nextLocal = ((Opcodes.ACC_STATIC & access) != 0) ? 0 : 1;
+ for (int i = 0; i < args.length; i++) {
+ state.nextLocal += args[i].getSize();
+ }
+ firstLocal = state.nextLocal;
+ }
+
+ public LocalVariablesSorter(LocalVariablesSorter lvs) {
+ super(lvs.mv);
+ state = lvs.state;
+ firstLocal = lvs.firstLocal;
+ }
+
+ public void visitVarInsn(final int opcode, final int var) {
+ int size;
+ switch (opcode) {
+ case Opcodes.LLOAD:
+ case Opcodes.LSTORE:
+ case Opcodes.DLOAD:
+ case Opcodes.DSTORE:
+ size = 2;
+ break;
+ default:
+ size = 1;
+ }
+ mv.visitVarInsn(opcode, remap(var, size));
+ }
+
+ public void visitIincInsn(final int var, final int increment) {
+ mv.visitIincInsn(remap(var, 1), increment);
+ }
+
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ mv.visitMaxs(maxStack, state.nextLocal);
+ }
+
+ public void visitLocalVariable(
+ final String name,
+ final String desc,
+ final String signature,
+ final Label start,
+ final Label end,
+ final int index)
+ {
+ mv.visitLocalVariable(name, desc, signature, start, end, remap(index));
+ }
+
+ protected int newLocal(final int size) {
+ int var = state.nextLocal;
+ state.nextLocal += size;
+ return var;
+ }
+
+ // -------------
+
+ private int remap(final int var, final int size) {
+ if (var < firstLocal) {
+ return var;
+ }
+ int key = 2 * var + size - 1;
+ int length = state.mapping.length;
+ if (key >= length) {
+ int[] newMapping = new int[Math.max(2 * length, key + 1)];
+ System.arraycopy(state.mapping, 0, newMapping, 0, length);
+ state.mapping = newMapping;
+ }
+ int value = state.mapping[key];
+ if (value == 0) {
+ value = state.nextLocal + 1;
+ state.mapping[key] = value;
+ state.nextLocal += size;
+ }
+ return value - 1;
+ }
+
+ private int remap(final int var) {
+ if (var < firstLocal) {
+ return var;
+ }
+ int key = 2 * var;
+ int value = key < state.mapping.length ? state.mapping[key] : 0;
+ if (value == 0) {
+ value = key + 1 < state.mapping.length ? state.mapping[key + 1] : 0;
+ }
+ if (value == 0) {
+ throw new IllegalStateException("Unknown local variable " + var);
+ }
+ return value - 1;
+ }
+
+ /**
+ * Mapping from old to new local variable indexes. A local variable at index
+ * i of size 1 is remapped to 'mapping[2*i]', while a local variable at
+ * index i of size 2 is remapped to 'mapping[2*i+1]'.
+ */
+ private static class State
+ {
+ int[] mapping = new int[40];
+ int nextLocal;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfo.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfo.java
new file mode 100644
index 0000000..c5d0ae2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfo.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+abstract public class MethodInfo {
+
+ protected MethodInfo() {
+ }
+
+ abstract public ClassInfo getClassInfo();
+ abstract public int getModifiers();
+ abstract public Signature getSignature();
+ abstract public Type[] getExceptionTypes();
+
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (!(o instanceof MethodInfo))
+ return false;
+ return getSignature().equals(((MethodInfo)o).getSignature());
+ }
+
+ public int hashCode() {
+ return getSignature().hashCode();
+ }
+
+ public String toString() {
+ // TODO: include modifiers, exceptions
+ return getSignature().toString();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfoTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfoTransformer.java
new file mode 100644
index 0000000..324e7b2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodInfoTransformer.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+public class MethodInfoTransformer implements Transformer
+{
+ private static final MethodInfoTransformer INSTANCE = new MethodInfoTransformer();
+
+ public static MethodInfoTransformer getInstance() {
+ return INSTANCE;
+ }
+
+ public Object transform(Object value) {
+ if (value instanceof Method) {
+ return ReflectUtils.getMethodInfo((Method)value);
+ } else if (value instanceof Constructor) {
+ return ReflectUtils.getMethodInfo((Constructor)value);
+ } else {
+ throw new IllegalArgumentException("cannot get method info for " + value);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodWrapper.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodWrapper.java
new file mode 100644
index 0000000..0fed4cb
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/MethodWrapper.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+public class MethodWrapper {
+ private static final MethodWrapperKey KEY_FACTORY =
+ (MethodWrapperKey)KeyFactory.create(MethodWrapperKey.class);
+
+ private MethodWrapper() {
+ }
+
+ public static Object create(Method method) {
+ return KEY_FACTORY.newInstance(method.getName(),
+ ReflectUtils.getNames(method.getParameterTypes()),
+ method.getReturnType().getName());
+ }
+
+ public static Set createSet(Collection methods) {
+ Set set = new HashSet();
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ set.add(create((Method)it.next()));
+ }
+ return set;
+ }
+
+ /** Internal interface, only public due to ClassLoader issues. */
+ public interface MethodWrapperKey {
+ public Object newInstance(String name, String[] parameterTypes, String returnType);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/NamingPolicy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/NamingPolicy.java
new file mode 100644
index 0000000..e1c3bd7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/NamingPolicy.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+/**
+ * Customize the generated class name for {@link AbstractClassGenerator}-based utilities.
+ */
+public interface NamingPolicy {
+ /**
+ * Choose a name for a generated class.
+ * @param prefix a dotted-name chosen by the generating class (possibly to put the generated class in a particular package)
+ * @param source the fully-qualified class name of the generating class (for example "org.powermock.api.mockito.repackaged.cglib.Enhancer")
+ * @param key A key object representing the state of the parameters; for caching to work properly, equal keys should result
+ * in the same generated class name. The default policy incorporates <code>key.hashCode()</code> into the class name.
+ * @param names a predicate that returns true if the given classname has already been used in the same ClassLoader.
+ * @return the fully-qualified class name
+ */
+ String getClassName(String prefix, String source, Object key, Predicate names);
+
+ /**
+ * The <code>NamingPolicy</code> in use does not currently, but may
+ * in the future, affect the caching of classes generated by {@link
+ * AbstractClassGenerator}, so this is a reminder that you should
+ * correctly implement <code>equals</code> and <code>hashCode</code>
+ * to avoid generating too many classes.
+ */
+ boolean equals(Object o);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ObjectSwitchCallback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ObjectSwitchCallback.java
new file mode 100644
index 0000000..43cd47e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ObjectSwitchCallback.java
@@ -0,0 +1,13 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+
+public interface ObjectSwitchCallback {
+ void processCase(Object key, Label end) throws Exception;
+ void processDefault() throws Exception;
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Predicate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Predicate.java
new file mode 100644
index 0000000..6e8fda6
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Predicate.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+public interface Predicate {
+ boolean evaluate(Object arg);
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessArrayCallback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessArrayCallback.java
new file mode 100644
index 0000000..69c814a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessArrayCallback.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+public interface ProcessArrayCallback {
+ void processElement(Type type);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessSwitchCallback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessSwitchCallback.java
new file mode 100644
index 0000000..f836057
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ProcessSwitchCallback.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+
+public interface ProcessSwitchCallback {
+ void processCase(int key, Label end) throws Exception;
+ void processDefault() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ReflectUtils.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ReflectUtils.java
new file mode 100644
index 0000000..7a59b18
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/ReflectUtils.java
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.beans.BeanInfo;
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @version $Id: ReflectUtils.java,v 1.29 2006/02/28 00:30:51 herbyderby Exp $
+ */
+public class ReflectUtils {
+ private static final Map primitives = new HashMap(8);
+ private static final Map transforms = new HashMap(8);
+ private static final ClassLoader defaultLoader = ReflectUtils.class.getClassLoader();
+ private static final ProtectionDomain PROTECTION_DOMAIN;
+ private static final String[] CGLIB_PACKAGES = {
+ "java.lang",
+ };
+ private static Method DEFINE_CLASS;
+
+ static {
+ PROTECTION_DOMAIN = (ProtectionDomain)AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return ReflectUtils.class.getProtectionDomain();
+ }
+ });
+
+ AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ try {
+ Class loader = Class.forName("java.lang.ClassLoader"); // JVM crash w/o this
+ DEFINE_CLASS = loader.getDeclaredMethod("defineClass",
+ new Class[]{ String.class,
+ byte[].class,
+ Integer.TYPE,
+ Integer.TYPE,
+ ProtectionDomain.class });
+ DEFINE_CLASS.setAccessible(true);
+ } catch (ClassNotFoundException e) {
+ throw new CodeGenerationException(e);
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+ return null;
+ }
+ });
+ }
+
+ static {
+ primitives.put("byte", Byte.TYPE);
+ primitives.put("char", Character.TYPE);
+ primitives.put("double", Double.TYPE);
+ primitives.put("float", Float.TYPE);
+ primitives.put("int", Integer.TYPE);
+ primitives.put("long", Long.TYPE);
+ primitives.put("short", Short.TYPE);
+ primitives.put("boolean", Boolean.TYPE);
+
+ transforms.put("byte", "B");
+ transforms.put("char", "C");
+ transforms.put("double", "D");
+ transforms.put("float", "F");
+ transforms.put("int", "I");
+ transforms.put("long", "J");
+ transforms.put("short", "S");
+ transforms.put("boolean", "Z");
+ }
+
+ private ReflectUtils() { }
+
+ public static Type[] getExceptionTypes(Member member) {
+ if (member instanceof Method) {
+ return TypeUtils.getTypes(((Method)member).getExceptionTypes());
+ } else if (member instanceof Constructor) {
+ return TypeUtils.getTypes(((Constructor)member).getExceptionTypes());
+ } else {
+ throw new IllegalArgumentException("Cannot get exception types of a field");
+ }
+ }
+
+ public static Signature getSignature(Member member) {
+ if (member instanceof Method) {
+ return new Signature(member.getName(), Type.getMethodDescriptor((Method)member));
+ } else if (member instanceof Constructor) {
+ Type[] types = TypeUtils.getTypes(((Constructor)member).getParameterTypes());
+ return new Signature(Constants.CONSTRUCTOR_NAME,
+ Type.getMethodDescriptor(Type.VOID_TYPE, types));
+
+ } else {
+ throw new IllegalArgumentException("Cannot get signature of a field");
+ }
+ }
+
+ public static Constructor findConstructor(String desc) {
+ return findConstructor(desc, defaultLoader);
+ }
+
+ public static Constructor findConstructor(String desc, ClassLoader loader) {
+ try {
+ int lparen = desc.indexOf('(');
+ String className = desc.substring(0, lparen).trim();
+ return getClass(className, loader).getConstructor(parseTypes(desc, loader));
+ } catch (ClassNotFoundException e) {
+ throw new CodeGenerationException(e);
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ public static Method findMethod(String desc) {
+ return findMethod(desc, defaultLoader);
+ }
+
+ public static Method findMethod(String desc, ClassLoader loader) {
+ try {
+ int lparen = desc.indexOf('(');
+ int dot = desc.lastIndexOf('.', lparen);
+ String className = desc.substring(0, dot).trim();
+ String methodName = desc.substring(dot + 1, lparen).trim();
+ return getClass(className, loader).getDeclaredMethod(methodName, parseTypes(desc, loader));
+ } catch (ClassNotFoundException e) {
+ throw new CodeGenerationException(e);
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ private static Class[] parseTypes(String desc, ClassLoader loader) throws ClassNotFoundException {
+ int lparen = desc.indexOf('(');
+ int rparen = desc.indexOf(')', lparen);
+ List params = new ArrayList();
+ int start = lparen + 1;
+ for (;;) {
+ int comma = desc.indexOf(',', start);
+ if (comma < 0) {
+ break;
+ }
+ params.add(desc.substring(start, comma).trim());
+ start = comma + 1;
+ }
+ if (start < rparen) {
+ params.add(desc.substring(start, rparen).trim());
+ }
+ Class[] types = new Class[params.size()];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = getClass((String)params.get(i), loader);
+ }
+ return types;
+ }
+
+ private static Class getClass(String className, ClassLoader loader) throws ClassNotFoundException {
+ return getClass(className, loader, CGLIB_PACKAGES);
+ }
+
+ private static Class getClass(String className, ClassLoader loader, String[] packages) throws ClassNotFoundException {
+ String save = className;
+ int dimensions = 0;
+ int index = 0;
+ while ((index = className.indexOf("[]", index) + 1) > 0) {
+ dimensions++;
+ }
+ StringBuffer brackets = new StringBuffer(className.length() - dimensions);
+ for (int i = 0; i < dimensions; i++) {
+ brackets.append('[');
+ }
+ className = className.substring(0, className.length() - 2 * dimensions);
+
+ String prefix = (dimensions > 0) ? brackets + "L" : "";
+ String suffix = (dimensions > 0) ? ";" : "";
+ try {
+ return Class.forName(prefix + className + suffix, false, loader);
+ } catch (ClassNotFoundException ignore) { }
+ for (int i = 0; i < packages.length; i++) {
+ try {
+ return Class.forName(prefix + packages[i] + '.' + className + suffix, false, loader);
+ } catch (ClassNotFoundException ignore) { }
+ }
+ if (dimensions == 0) {
+ Class c = (Class)primitives.get(className);
+ if (c != null) {
+ return c;
+ }
+ } else {
+ String transform = (String)transforms.get(className);
+ if (transform != null) {
+ try {
+ return Class.forName(brackets + transform, false, loader);
+ } catch (ClassNotFoundException ignore) { }
+ }
+ }
+ throw new ClassNotFoundException(save);
+ }
+
+
+ public static Object newInstance(Class type) {
+ return newInstance(type, Constants.EMPTY_CLASS_ARRAY, null);
+ }
+
+ public static Object newInstance(Class type, Class[] parameterTypes, Object[] args) {
+ return newInstance(getConstructor(type, parameterTypes), args);
+ }
+
+ public static Object newInstance(final Constructor cstruct, final Object[] args) {
+
+ boolean flag = cstruct.isAccessible();
+ try {
+ cstruct.setAccessible(true);
+ Object result = cstruct.newInstance(args);
+ return result;
+ } catch (InstantiationException e) {
+ throw new CodeGenerationException(e);
+ } catch (IllegalAccessException e) {
+ throw new CodeGenerationException(e);
+ } catch (InvocationTargetException e) {
+ throw new CodeGenerationException(e.getTargetException());
+ } finally {
+ cstruct.setAccessible(flag);
+ }
+
+ }
+
+ public static Constructor getConstructor(Class type, Class[] parameterTypes) {
+ try {
+ Constructor constructor = type.getDeclaredConstructor(parameterTypes);
+ constructor.setAccessible(true);
+ return constructor;
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ public static String[] getNames(Class[] classes)
+ {
+ if (classes == null)
+ return null;
+ String[] names = new String[classes.length];
+ for (int i = 0; i < names.length; i++) {
+ names[i] = classes[i].getName();
+ }
+ return names;
+ }
+
+ public static Class[] getClasses(Object[] objects) {
+ Class[] classes = new Class[objects.length];
+ for (int i = 0; i < objects.length; i++) {
+ classes[i] = objects[i].getClass();
+ }
+ return classes;
+ }
+
+ public static Method findNewInstance(Class iface) {
+ Method m = findInterfaceMethod(iface);
+ if (!m.getName().equals("newInstance")) {
+ throw new IllegalArgumentException(iface + " missing newInstance method");
+ }
+ return m;
+ }
+
+ public static Method[] getPropertyMethods(PropertyDescriptor[] properties, boolean read, boolean write) {
+ Set methods = new HashSet();
+ for (int i = 0; i < properties.length; i++) {
+ PropertyDescriptor pd = properties[i];
+ if (read) {
+ methods.add(pd.getReadMethod());
+ }
+ if (write) {
+ methods.add(pd.getWriteMethod());
+ }
+ }
+ methods.remove(null);
+ return (Method[])methods.toArray(new Method[methods.size()]);
+ }
+
+ public static PropertyDescriptor[] getBeanProperties(Class type) {
+ return getPropertiesHelper(type, true, true);
+ }
+
+ public static PropertyDescriptor[] getBeanGetters(Class type) {
+ return getPropertiesHelper(type, true, false);
+ }
+
+ public static PropertyDescriptor[] getBeanSetters(Class type) {
+ return getPropertiesHelper(type, false, true);
+ }
+
+ private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
+ try {
+ BeanInfo info = Introspector.getBeanInfo(type, Object.class);
+ PropertyDescriptor[] all = info.getPropertyDescriptors();
+ if (read && write) {
+ return all;
+ }
+ List properties = new ArrayList(all.length);
+ for (int i = 0; i < all.length; i++) {
+ PropertyDescriptor pd = all[i];
+ if ((read && pd.getReadMethod() != null) ||
+ (write && pd.getWriteMethod() != null)) {
+ properties.add(pd);
+ }
+ }
+ return (PropertyDescriptor[])properties.toArray(new PropertyDescriptor[properties.size()]);
+ } catch (IntrospectionException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+
+
+ public static Method findDeclaredMethod(final Class type,
+ final String methodName, final Class[] parameterTypes)
+ throws NoSuchMethodException {
+
+ Class cl = type;
+ while (cl != null) {
+ try {
+ return cl.getDeclaredMethod(methodName, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ cl = cl.getSuperclass();
+ }
+ }
+ throw new NoSuchMethodException(methodName);
+
+ }
+
+ public static List addAllMethods(final Class type, final List list) {
+
+
+ list.addAll(Arrays.asList(type.getDeclaredMethods()));
+ Class superclass = type.getSuperclass();
+ if (superclass != null) {
+ addAllMethods(superclass, list);
+ }
+ Class[] interfaces = type.getInterfaces();
+ for (int i = 0; i < interfaces.length; i++) {
+ addAllMethods(interfaces[i], list);
+ }
+
+ return list;
+ }
+
+ public static List addAllInterfaces(Class type, List list) {
+ Class superclass = type.getSuperclass();
+ if (superclass != null) {
+ list.addAll(Arrays.asList(type.getInterfaces()));
+ addAllInterfaces(superclass, list);
+ }
+ return list;
+ }
+
+
+ public static Method findInterfaceMethod(Class iface) {
+ if (!iface.isInterface()) {
+ throw new IllegalArgumentException(iface + " is not an interface");
+ }
+ Method[] methods = iface.getDeclaredMethods();
+ if (methods.length != 1) {
+ throw new IllegalArgumentException("expecting exactly 1 method in " + iface);
+ }
+ return methods[0];
+ }
+
+ public static Class defineClass(String className, byte[] b, ClassLoader loader) throws Exception {
+ Object[] args = new Object[]{className, b, new Integer(0), new Integer(b.length), PROTECTION_DOMAIN };
+ return (Class)DEFINE_CLASS.invoke(loader, args);
+ }
+
+ public static int findPackageProtected(Class[] classes) {
+ for (int i = 0; i < classes.length; i++) {
+ if (!Modifier.isPublic(classes[i].getModifiers())) {
+ return i;
+ }
+ }
+ return 0;
+ }
+
+ public static MethodInfo getMethodInfo(final Member member, final int modifiers) {
+ final Signature sig = getSignature(member);
+ return new MethodInfo() {
+ private ClassInfo ci;
+ public ClassInfo getClassInfo() {
+ if (ci == null)
+ ci = ReflectUtils.getClassInfo(member.getDeclaringClass());
+ return ci;
+ }
+ public int getModifiers() {
+ return modifiers;
+ }
+ public Signature getSignature() {
+ return sig;
+ }
+ public Type[] getExceptionTypes() {
+ return ReflectUtils.getExceptionTypes(member);
+ }
+ public Attribute getAttribute() {
+ return null;
+ }
+ };
+ }
+
+ public static MethodInfo getMethodInfo(Member member) {
+ return getMethodInfo(member, member.getModifiers());
+ }
+
+ public static ClassInfo getClassInfo(final Class clazz) {
+ final Type type = Type.getType(clazz);
+ final Type sc = (clazz.getSuperclass() == null) ? null : Type.getType(clazz.getSuperclass());
+ return new ClassInfo() {
+ public Type getType() {
+ return type;
+ }
+ public Type getSuperType() {
+ return sc;
+ }
+ public Type[] getInterfaces() {
+ return TypeUtils.getTypes(clazz.getInterfaces());
+ }
+ public int getModifiers() {
+ return clazz.getModifiers();
+ }
+ };
+ }
+
+ // used by MethodInterceptorGenerated generated code
+ public static Method[] findMethods(String[] namesAndDescriptors, Method[] methods)
+ {
+ Map map = new HashMap();
+ for (int i = 0; i < methods.length; i++) {
+ Method method = methods[i];
+ map.put(method.getName() + Type.getMethodDescriptor(method), method);
+ }
+ Method[] result = new Method[namesAndDescriptors.length / 2];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = (Method)map.get(namesAndDescriptors[i * 2] + namesAndDescriptors[i * 2 + 1]);
+ if (result[i] == null) {
+ // TODO: error?
+ }
+ }
+ return result;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/RejectModifierPredicate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/RejectModifierPredicate.java
new file mode 100644
index 0000000..576eda4
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/RejectModifierPredicate.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import java.lang.reflect.Member;
+
+public class RejectModifierPredicate implements Predicate {
+ private int rejectMask;
+
+ public RejectModifierPredicate(int rejectMask) {
+ this.rejectMask = rejectMask;
+ }
+
+ public boolean evaluate(Object arg) {
+ return (((Member)arg).getModifiers() & rejectMask) == 0;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Signature.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Signature.java
new file mode 100644
index 0000000..63721d1
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Signature.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+/**
+ * A representation of a method signature, containing the method name,
+ * return type, and parameter types.
+ */
+public class Signature {
+ private String name;
+ private String desc;
+
+ public Signature(String name, String desc) {
+ // TODO: better error checking
+ if (name.indexOf('(') >= 0) {
+ throw new IllegalArgumentException("Name '" + name + "' is invalid");
+ }
+ this.name = name;
+ this.desc = desc;
+ }
+
+ public Signature(String name, Type returnType, Type[] argumentTypes) {
+ this(name, Type.getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getDescriptor() {
+ return desc;
+ }
+
+ public Type getReturnType() {
+ return Type.getReturnType(desc);
+ }
+
+ public Type[] getArgumentTypes() {
+ return Type.getArgumentTypes(desc);
+ }
+
+ public String toString() {
+ return name + desc;
+ }
+
+ public boolean equals(Object o) {
+ if (o == null)
+ return false;
+ if (!(o instanceof Signature))
+ return false;
+ Signature other = (Signature)o;
+ return name.equals(other.name) && desc.equals(other.desc);
+ }
+
+ public int hashCode() {
+ return name.hashCode() ^ desc.hashCode();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TinyBitSet.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TinyBitSet.java
new file mode 100644
index 0000000..aaf6051
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TinyBitSet.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+public class TinyBitSet {
+ private static int[] T = new int[256];
+
+ static {
+ for(int j = 0; j < 256; j++) {
+ T[j] = gcount(j);
+ }
+ }
+
+ private int value = 0;
+
+ private static int gcount(int x) {
+ int c = 0;
+ while (x != 0) {
+ c++;
+ x &= (x - 1);
+ }
+ return c;
+ }
+
+ private static int topbit(int i) {
+ int j;
+ for (j = 0; i != 0; i ^= j) {
+ j = i & -i;
+ }
+ return j;
+ }
+
+ private static int log2(int i) {
+ int j = 0;
+ for (j = 0; i != 0; i >>= 1) {
+ j++;
+ }
+ return j;
+ }
+
+ public int length() {
+ return log2(topbit(value));
+ }
+
+ public int cardinality() {
+ int w = value;
+ int c = 0;
+ while (w != 0) {
+ c += T[w & 255];
+ w >>= 8;
+ }
+ return c;
+ }
+
+ public boolean get(int index) {
+ return (value & (1 << index)) != 0;
+ }
+
+ public void set(int index) {
+ value |= (1 << index);
+ }
+
+ public void clear(int index) {
+ value &= ~(1 << index);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Transformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Transformer.java
new file mode 100644
index 0000000..02c50f6
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/Transformer.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+public interface Transformer {
+ Object transform(Object value);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TypeUtils.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TypeUtils.java
new file mode 100644
index 0000000..8fe9d41
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/TypeUtils.java
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public class TypeUtils {
+ private static final Map transforms = new HashMap();
+ private static final Map rtransforms = new HashMap();
+
+ static {
+ transforms.put("void", "V");
+ transforms.put("byte", "B");
+ transforms.put("char", "C");
+ transforms.put("double", "D");
+ transforms.put("float", "F");
+ transforms.put("int", "I");
+ transforms.put("long", "J");
+ transforms.put("short", "S");
+ transforms.put("boolean", "Z");
+
+ CollectionUtils.reverse(transforms, rtransforms);
+ }
+
+ private TypeUtils() {
+ }
+
+ public static Type getType(String className) {
+ return Type.getType("L" + className.replace('.', '/') + ";");
+ }
+
+ public static boolean isFinal(int access) {
+ return (Constants.ACC_FINAL & access) != 0;
+ }
+
+ public static boolean isStatic(int access) {
+ return (Constants.ACC_STATIC & access) != 0;
+ }
+
+ public static boolean isProtected(int access) {
+ return (Constants.ACC_PROTECTED & access) != 0;
+ }
+
+ public static boolean isPublic(int access) {
+ return (Constants.ACC_PUBLIC & access) != 0;
+ }
+
+ public static boolean isAbstract(int access) {
+ return (Constants.ACC_ABSTRACT & access) != 0;
+ }
+
+ public static boolean isInterface(int access) {
+ return (Constants.ACC_INTERFACE & access) != 0;
+ }
+
+ public static boolean isPrivate(int access) {
+ return (Constants.ACC_PRIVATE & access) != 0;
+ }
+
+ public static boolean isSynthetic(int access) {
+ return (Constants.ACC_SYNTHETIC & access) != 0;
+ }
+
+ // getPackage returns null on JDK 1.2
+ public static String getPackageName(Type type) {
+ return getPackageName(getClassName(type));
+ }
+
+ public static String getPackageName(String className) {
+ int idx = className.lastIndexOf('.');
+ return (idx < 0) ? "" : className.substring(0, idx);
+ }
+
+ public static String upperFirst(String s) {
+ if (s == null || s.length() == 0) {
+ return s;
+ }
+ return Character.toUpperCase(s.charAt(0)) + s.substring(1);
+ }
+
+ public static String getClassName(Type type) {
+ if (isPrimitive(type)) {
+ return (String)rtransforms.get(type.getDescriptor());
+ } else if (isArray(type)) {
+ return getClassName(getComponentType(type)) + "[]";
+ } else {
+ return type.getClassName();
+ }
+ }
+
+ public static Type[] add(Type[] types, Type extra) {
+ if (types == null) {
+ return new Type[]{ extra };
+ } else {
+ List list = Arrays.asList(types);
+ if (list.contains(extra)) {
+ return types;
+ }
+ Type[] copy = new Type[types.length + 1];
+ System.arraycopy(types, 0, copy, 0, types.length);
+ copy[types.length] = extra;
+ return copy;
+ }
+ }
+
+ public static Type[] add(Type[] t1, Type[] t2) {
+ // TODO: set semantics?
+ Type[] all = new Type[t1.length + t2.length];
+ System.arraycopy(t1, 0, all, 0, t1.length);
+ System.arraycopy(t2, 0, all, t1.length, t2.length);
+ return all;
+ }
+
+ public static Type fromInternalName(String name) {
+ // TODO; primitives?
+ return Type.getType("L" + name + ";");
+ }
+
+ public static Type[] fromInternalNames(String[] names) {
+ if (names == null) {
+ return null;
+ }
+ Type[] types = new Type[names.length];
+ for (int i = 0; i < names.length; i++) {
+ types[i] = fromInternalName(names[i]);
+ }
+ return types;
+ }
+
+ public static int getStackSize(Type[] types) {
+ int size = 0;
+ for (int i = 0; i < types.length; i++) {
+ size += types[i].getSize();
+ }
+ return size;
+ }
+
+ public static String[] toInternalNames(Type[] types) {
+ if (types == null) {
+ return null;
+ }
+ String[] names = new String[types.length];
+ for (int i = 0; i < types.length; i++) {
+ names[i] = types[i].getInternalName();
+ }
+ return names;
+ }
+
+ public static Signature parseSignature(String s) {
+ int space = s.indexOf(' ');
+ int lparen = s.indexOf('(', space);
+ int rparen = s.indexOf(')', lparen);
+ String returnType = s.substring(0, space);
+ String methodName = s.substring(space + 1, lparen);
+ StringBuffer sb = new StringBuffer();
+ sb.append('(');
+ for (Iterator it = parseTypes(s, lparen + 1, rparen).iterator(); it.hasNext();) {
+ sb.append(it.next());
+ }
+ sb.append(')');
+ sb.append(map(returnType));
+ return new Signature(methodName, sb.toString());
+ }
+
+ public static Type parseType(String s) {
+ return Type.getType(map(s));
+ }
+
+ public static Type[] parseTypes(String s) {
+ List names = parseTypes(s, 0, s.length());
+ Type[] types = new Type[names.size()];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = Type.getType((String)names.get(i));
+ }
+ return types;
+ }
+
+ public static Signature parseConstructor(Type[] types) {
+ StringBuffer sb = new StringBuffer();
+ sb.append("(");
+ for (int i = 0; i < types.length; i++) {
+ sb.append(types[i].getDescriptor());
+ }
+ sb.append(")");
+ sb.append("V");
+ return new Signature(Constants.CONSTRUCTOR_NAME, sb.toString());
+ }
+
+ public static Signature parseConstructor(String sig) {
+ return parseSignature("void <init>(" + sig + ")"); // TODO
+ }
+
+ private static List parseTypes(String s, int mark, int end) {
+ List types = new ArrayList(5);
+ for (;;) {
+ int next = s.indexOf(',', mark);
+ if (next < 0) {
+ break;
+ }
+ types.add(map(s.substring(mark, next).trim()));
+ mark = next + 1;
+ }
+ types.add(map(s.substring(mark, end).trim()));
+ return types;
+ }
+
+ private static String map(String type) {
+ if (type.equals("")) {
+ return type;
+ }
+ String t = (String)transforms.get(type);
+ if (t != null) {
+ return t;
+ } else if (type.indexOf('.') < 0) {
+ return map("java.lang." + type);
+ } else {
+ StringBuffer sb = new StringBuffer();
+ int index = 0;
+ while ((index = type.indexOf("[]", index) + 1) > 0) {
+ sb.append('[');
+ }
+ type = type.substring(0, type.length() - sb.length() * 2);
+ sb.append('L').append(type.replace('.', '/')).append(';');
+ return sb.toString();
+ }
+ }
+
+ public static Type getBoxedType(Type type) {
+ switch (type.getSort()) {
+ case Type.CHAR:
+ return Constants.TYPE_CHARACTER;
+ case Type.BOOLEAN:
+ return Constants.TYPE_BOOLEAN;
+ case Type.DOUBLE:
+ return Constants.TYPE_DOUBLE;
+ case Type.FLOAT:
+ return Constants.TYPE_FLOAT;
+ case Type.LONG:
+ return Constants.TYPE_LONG;
+ case Type.INT:
+ return Constants.TYPE_INTEGER;
+ case Type.SHORT:
+ return Constants.TYPE_SHORT;
+ case Type.BYTE:
+ return Constants.TYPE_BYTE;
+ default:
+ return type;
+ }
+ }
+
+ public static Type getUnboxedType(Type type) {
+ if (Constants.TYPE_INTEGER.equals(type)) {
+ return Type.INT_TYPE;
+ } else if (Constants.TYPE_BOOLEAN.equals(type)) {
+ return Type.BOOLEAN_TYPE;
+ } else if (Constants.TYPE_DOUBLE.equals(type)) {
+ return Type.DOUBLE_TYPE;
+ } else if (Constants.TYPE_LONG.equals(type)) {
+ return Type.LONG_TYPE;
+ } else if (Constants.TYPE_CHARACTER.equals(type)) {
+ return Type.CHAR_TYPE;
+ } else if (Constants.TYPE_BYTE.equals(type)) {
+ return Type.BYTE_TYPE;
+ } else if (Constants.TYPE_FLOAT.equals(type)) {
+ return Type.FLOAT_TYPE;
+ } else if (Constants.TYPE_SHORT.equals(type)) {
+ return Type.SHORT_TYPE;
+ } else {
+ return type;
+ }
+ }
+
+ public static boolean isArray(Type type) {
+ return type.getSort() == Type.ARRAY;
+ }
+
+ public static Type getComponentType(Type type) {
+ if (!isArray(type)) {
+ throw new IllegalArgumentException("Type " + type + " is not an array");
+ }
+ return Type.getType(type.getDescriptor().substring(1));
+ }
+
+ public static boolean isPrimitive(Type type) {
+ switch (type.getSort()) {
+ case Type.ARRAY:
+ case Type.OBJECT:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ public static String emulateClassGetName(Type type) {
+ if (isArray(type)) {
+ return type.getDescriptor().replace('/', '.');
+ } else {
+ return getClassName(type);
+ }
+ }
+
+ public static boolean isConstructor(MethodInfo method) {
+ return method.getSignature().getName().equals(Constants.CONSTRUCTOR_NAME);
+ }
+
+ public static Type[] getTypes(Class[] classes) {
+ if (classes == null) {
+ return null;
+ }
+ Type[] types = new Type[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ types[i] = Type.getType(classes[i]);
+ }
+ return types;
+ }
+
+ public static int ICONST(int value) {
+ switch (value) {
+ case -1: return Constants.ICONST_M1;
+ case 0: return Constants.ICONST_0;
+ case 1: return Constants.ICONST_1;
+ case 2: return Constants.ICONST_2;
+ case 3: return Constants.ICONST_3;
+ case 4: return Constants.ICONST_4;
+ case 5: return Constants.ICONST_5;
+ }
+ return -1; // error
+ }
+
+ public static int LCONST(long value) {
+ if (value == 0L) {
+ return Constants.LCONST_0;
+ } else if (value == 1L) {
+ return Constants.LCONST_1;
+ } else {
+ return -1; // error
+ }
+ }
+
+ public static int FCONST(float value) {
+ if (value == 0f) {
+ return Constants.FCONST_0;
+ } else if (value == 1f) {
+ return Constants.FCONST_1;
+ } else if (value == 2f) {
+ return Constants.FCONST_2;
+ } else {
+ return -1; // error
+ }
+ }
+
+ public static int DCONST(double value) {
+ if (value == 0d) {
+ return Constants.DCONST_0;
+ } else if (value == 1d) {
+ return Constants.DCONST_1;
+ } else {
+ return -1; // error
+ }
+ }
+
+ public static int NEWARRAY(Type type) {
+ switch (type.getSort()) {
+ case Type.BYTE:
+ return Constants.T_BYTE;
+ case Type.CHAR:
+ return Constants.T_CHAR;
+ case Type.DOUBLE:
+ return Constants.T_DOUBLE;
+ case Type.FLOAT:
+ return Constants.T_FLOAT;
+ case Type.INT:
+ return Constants.T_INT;
+ case Type.LONG:
+ return Constants.T_LONG;
+ case Type.SHORT:
+ return Constants.T_SHORT;
+ case Type.BOOLEAN:
+ return Constants.T_BOOLEAN;
+ default:
+ return -1; // error
+ }
+ }
+
+ public static String escapeType(String s) {
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0, len = s.length(); i < len; i++) {
+ char c = s.charAt(i);
+ switch (c) {
+ case '$': sb.append("$24"); break;
+ case '.': sb.append("$2E"); break;
+ case '[': sb.append("$5B"); break;
+ case ';': sb.append("$3B"); break;
+ case '(': sb.append("$28"); break;
+ case ')': sb.append("$29"); break;
+ case '/': sb.append("$2F"); break;
+ default:
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/VisibilityPredicate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/VisibilityPredicate.java
new file mode 100644
index 0000000..f8f8470
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/core/VisibilityPredicate.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.core;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+import java.lang.reflect.Member;
+import java.lang.reflect.Modifier;
+
+public class VisibilityPredicate implements Predicate {
+ private boolean protectedOk;
+ private String pkg;
+
+ public VisibilityPredicate(Class source, boolean protectedOk) {
+ this.protectedOk = protectedOk;
+ pkg = TypeUtils.getPackageName(Type.getType(source));
+ }
+
+ public boolean evaluate(Object arg) {
+ int mod = (arg instanceof Member) ? ((Member)arg).getModifiers() : ((Integer)arg).intValue();
+ if (Modifier.isPrivate(mod)) {
+ return false;
+ } else if (Modifier.isPublic(mod)) {
+ return true;
+ } else if (Modifier.isProtected(mod)) {
+ return protectedOk;
+ } else {
+ return pkg.equals(TypeUtils.getPackageName(Type.getType(((Member)arg).getDeclaringClass())));
+ }
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Callback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Callback.java
new file mode 100644
index 0000000..6a3b862
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Callback.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * All callback interfaces used by {@link Enhancer} extend this interface.
+ * @see MethodInterceptor
+ * @see NoOp
+ * @see LazyLoader
+ * @see Dispatcher
+ * @see InvocationHandler
+ * @see FixedValue
+ */
+public interface Callback
+{
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackFilter.java
new file mode 100644
index 0000000..3881627
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackFilter.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * Map methods of subclasses generated by {@link Enhancer} to a particular
+ * callback. The type of the callbacks chosen for each method affects
+ * the bytecode generated for that method in the subclass, and cannot
+ * change for the life of the class.
+ */
+public interface CallbackFilter {
+ /**
+ * Map a method to a callback.
+ *
+ * @param method the intercepted method
+ * @param allMethods all the methods found on the instance. Don't mess with the contents of this list!!!
+ * @return the index into the array of callbacks (as specified by {@link Enhancer#setCallbacks}) to use for the method,
+ */
+ int accept(Method method, List<Method> allMethods);
+
+ /**
+ * The <code>CallbackFilter</code> in use affects which cached class
+ * the <code>Enhancer</code> will use, so this is a reminder that
+ * you should correctly implement <code>equals</code> and
+ * <code>hashCode</code> for custom <code>CallbackFilter</code>
+ * implementations in order to improve performance.
+ */
+ boolean equals(Object o);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackGenerator.java
new file mode 100644
index 0000000..299060e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackGenerator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+
+import java.util.List;
+
+interface CallbackGenerator
+{
+ void generate(ClassEmitter ce, Context context, List methods) throws Exception;
+ void generateStatic(CodeEmitter e, Context context, List methods) throws Exception;
+
+ interface Context
+ {
+ ClassLoader getClassLoader();
+ CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method);
+ int getOriginalModifiers(MethodInfo method);
+ int getIndex(MethodInfo method);
+ void emitCallback(CodeEmitter ce, int index);
+ Signature getImplSignature(MethodInfo method);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackHelper.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackHelper.java
new file mode 100644
index 0000000..82c3189
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackHelper.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @version $Id: CallbackHelper.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $
+ */
+abstract public class CallbackHelper
+implements CallbackFilter
+{
+ private Map methodMap = new HashMap();
+ private List callbacks = new ArrayList();
+
+ public CallbackHelper(Class superclass, Class[] interfaces)
+ {
+ List methods = new ArrayList();
+ Enhancer.getMethods(superclass, interfaces, methods);
+ Map indexes = new HashMap();
+ for (int i = 0, size = methods.size(); i < size; i++) {
+ Method method = (Method)methods.get(i);
+ Object callback = getCallback(method);
+ if (callback == null)
+ throw new IllegalStateException("getCallback cannot return null");
+ boolean isCallback = callback instanceof Callback;
+ if (!(isCallback || (callback instanceof Class)))
+ throw new IllegalStateException("getCallback must return a Callback or a Class");
+ if (i > 0 && ((callbacks.get(i - 1) instanceof Callback) ^ isCallback))
+ throw new IllegalStateException("getCallback must return a Callback or a Class consistently for every Method");
+ Integer index = (Integer)indexes.get(callback);
+ if (index == null) {
+ index = new Integer(callbacks.size());
+ indexes.put(callback, index);
+ }
+ methodMap.put(method, index);
+ callbacks.add(callback);
+ }
+ }
+
+ abstract protected Object getCallback(Method method);
+
+ public Callback[] getCallbacks()
+ {
+ if (callbacks.size() == 0)
+ return new Callback[0];
+ if (callbacks.get(0) instanceof Callback) {
+ return (Callback[])callbacks.toArray(new Callback[callbacks.size()]);
+ } else {
+ throw new IllegalStateException("getCallback returned classes, not callbacks; call getCallbackTypes instead");
+ }
+ }
+
+ public Class[] getCallbackTypes()
+ {
+ if (callbacks.size() == 0)
+ return new Class[0];
+ if (callbacks.get(0) instanceof Callback) {
+ return ReflectUtils.getClasses(getCallbacks());
+ } else {
+ return (Class[])callbacks.toArray(new Class[callbacks.size()]);
+ }
+ }
+
+ public int accept(Method method, List<Method> allMethods)
+ {
+ return ((Integer)methodMap.get(method)).intValue();
+ }
+
+ public int hashCode()
+ {
+ return methodMap.hashCode();
+ }
+
+ public boolean equals(Object o)
+ {
+ if (o == null)
+ return false;
+ if (!(o instanceof CallbackHelper))
+ return false;
+ return methodMap.equals(((CallbackHelper)o).methodMap);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackInfo.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackInfo.java
new file mode 100644
index 0000000..221f85f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/CallbackInfo.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+class CallbackInfo
+{
+ private static final CallbackInfo[] CALLBACKS = {
+ new CallbackInfo(NoOp.class, NoOpGenerator.INSTANCE),
+ new CallbackInfo(MethodInterceptor.class, MethodInterceptorGenerator.INSTANCE),
+ new CallbackInfo(InvocationHandler.class, InvocationHandlerGenerator.INSTANCE),
+ new CallbackInfo(LazyLoader.class, LazyLoaderGenerator.INSTANCE),
+ new CallbackInfo(Dispatcher.class, DispatcherGenerator.INSTANCE),
+ new CallbackInfo(FixedValue.class, FixedValueGenerator.INSTANCE),
+ new CallbackInfo(ProxyRefDispatcher.class, DispatcherGenerator.PROXY_REF_INSTANCE),
+ };
+ private Class cls;
+ private CallbackGenerator generator;
+
+ //////////////////// PRIVATE ////////////////////
+ private Type type;
+ private CallbackInfo(Class cls, CallbackGenerator generator) {
+ this.cls = cls;
+ this.generator = generator;
+ type = Type.getType(cls);
+ }
+
+ public static Type[] determineTypes(Class[] callbackTypes) {
+ Type[] types = new Type[callbackTypes.length];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = determineType(callbackTypes[i]);
+ }
+ return types;
+ }
+
+ public static Type[] determineTypes(Callback[] callbacks) {
+ Type[] types = new Type[callbacks.length];
+ for (int i = 0; i < types.length; i++) {
+ types[i] = determineType(callbacks[i]);
+ }
+ return types;
+ }
+
+ public static CallbackGenerator[] getGenerators(Type[] callbackTypes) {
+ CallbackGenerator[] generators = new CallbackGenerator[callbackTypes.length];
+ for (int i = 0; i < generators.length; i++) {
+ generators[i] = getGenerator(callbackTypes[i]);
+ }
+ return generators;
+ }
+
+ private static Type determineType(Callback callback) {
+ if (callback == null) {
+ throw new IllegalStateException("Callback is null");
+ }
+ return determineType(callback.getClass());
+ }
+
+ private static Type determineType(Class callbackType) {
+ Class cur = null;
+ for (int i = 0; i < CALLBACKS.length; i++) {
+ CallbackInfo info = CALLBACKS[i];
+ if (info.cls.isAssignableFrom(callbackType)) {
+ if (cur != null) {
+ throw new IllegalStateException("Callback implements both " + cur + " and " + info.cls);
+ }
+ cur = info.cls;
+ }
+ }
+ if (cur == null) {
+ throw new IllegalStateException("Unknown callback type " + callbackType);
+ }
+ return Type.getType(cur);
+ }
+
+ private static CallbackGenerator getGenerator(Type callbackType) {
+ for (int i = 0; i < CALLBACKS.length; i++) {
+ CallbackInfo info = CALLBACKS[i];
+ if (info.type.equals(callbackType)) {
+ return info.generator;
+ }
+ }
+ throw new IllegalStateException("Unknown callback type " + callbackType);
+ }
+}
+
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Dispatcher.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Dispatcher.java
new file mode 100644
index 0000000..f51263c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Dispatcher.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * Dispatching {@link Enhancer} callback. This is identical to the
+ * {@link LazyLoader} interface but needs to be separate so that <code>Enhancer</code>
+ * knows which type of code to generate.
+ */
+public interface Dispatcher extends Callback {
+ /**
+ * Return the object which the original method invocation should
+ * be dispatched. This method is called for <b>every</b> method invocation.
+ * @return an object that can invoke the method
+ */
+ Object loadObject() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/DispatcherGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/DispatcherGenerator.java
new file mode 100644
index 0000000..58b8711
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/DispatcherGenerator.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.Iterator;
+import java.util.List;
+
+class DispatcherGenerator implements CallbackGenerator {
+ public static final DispatcherGenerator INSTANCE =
+ new DispatcherGenerator(false);
+ public static final DispatcherGenerator PROXY_REF_INSTANCE =
+ new DispatcherGenerator(true);
+
+ private static final Type DISPATCHER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.Dispatcher");
+ private static final Type PROXY_REF_DISPATCHER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.ProxyRefDispatcher");
+ private static final Signature LOAD_OBJECT =
+ TypeUtils.parseSignature("Object loadObject()");
+ private static final Signature PROXY_REF_LOAD_OBJECT =
+ TypeUtils.parseSignature("Object loadObject(Object)");
+
+ private boolean proxyRef;
+
+ private DispatcherGenerator(boolean proxyRef) {
+ this.proxyRef = proxyRef;
+ }
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ if (!TypeUtils.isProtected(method.getModifiers())) {
+ CodeEmitter e = context.beginMethod(ce, method);
+ context.emitCallback(e, context.getIndex(method));
+ if (proxyRef) {
+ e.load_this();
+ e.invoke_interface(PROXY_REF_DISPATCHER, PROXY_REF_LOAD_OBJECT);
+ } else {
+ e.invoke_interface(DISPATCHER, LOAD_OBJECT);
+ }
+ e.checkcast(method.getClassInfo().getType());
+ e.load_args();
+ e.invoke(method);
+ e.return_value();
+ e.end_method();
+ }
+ }
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) { }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Enhancer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Enhancer.java
new file mode 100644
index 0000000..7988b6c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Enhancer.java
@@ -0,0 +1,1059 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.CollectionUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.DuplicatesPredicate;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfoTransformer;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodWrapper;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ProcessSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.RejectModifierPredicate;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.Transformer;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.VisibilityPredicate;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Generates dynamic subclasses to enable method interception. This
+ * class started as a substitute for the standard Dynamic Proxy support
+ * included with JDK 1.3, but one that allowed the proxies to extend a
+ * concrete base class, in addition to implementing interfaces. The dynamically
+ * generated subclasses override the non-final methods of the superclass and
+ * have hooks which callback to user-defined interceptor
+ * implementations.
+ * <p>
+ * The original and most general callback type is the {@link MethodInterceptor}, which
+ * in AOP terms enables "around advice"--that is, you can invoke custom code both before
+ * and after the invocation of the "super" method. In addition you can modify the
+ * arguments before calling the super method, or not call it at all.
+ * <p>
+ * Although <code>MethodInterceptor</code> is generic enough to meet any
+ * interception need, it is often overkill. For simplicity and performance, additional
+ * specialized callback types, such as {@link LazyLoader} are also available.
+ * Often a single callback will be used per enhanced class, but you can control
+ * which callback is used on a per-method basis with a {@link CallbackFilter}.
+ * <p>
+ * The most common uses of this class are embodied in the static helper methods. For
+ * advanced needs, such as customizing the <code>ClassLoader</code> to use, you should create
+ * a new instance of <code>Enhancer</code>. Other classes within CGLIB follow a similar pattern.
+ * <p>
+ * All enhanced objects implement the {@link Factory} interface, unless {@link #setUseFactory} is
+ * used to explicitly disable this feature. The <code>Factory</code> interface provides an API
+ * to change the callbacks of an existing object, as well as a faster and easier way to create
+ * new instances of the same type.
+ * <p>
+ * For an almost drop-in replacement for
+ * <code>java.lang.reflect.Proxy</code>, see the {@link Proxy} class.
+ */
+public class Enhancer extends AbstractClassGenerator
+{
+ private static final CallbackFilter ALL_ZERO = new CallbackFilter(){
+ public int accept(Method method, List<Method> allMethods) {
+ return 0;
+ }
+ };
+
+ private static final Source SOURCE = new Source(Enhancer.class.getName());
+ private static final EnhancerKey KEY_FACTORY =
+ (EnhancerKey) KeyFactory.create(EnhancerKey.class);
+
+ private static final String BOUND_FIELD = "CGLIB$BOUND";
+ private static final String THREAD_CALLBACKS_FIELD = "CGLIB$THREAD_CALLBACKS";
+ private static final String STATIC_CALLBACKS_FIELD = "CGLIB$STATIC_CALLBACKS";
+ private static final String SET_THREAD_CALLBACKS_NAME = "CGLIB$SET_THREAD_CALLBACKS";
+ private static final String SET_STATIC_CALLBACKS_NAME = "CGLIB$SET_STATIC_CALLBACKS";
+ private static final String CONSTRUCTED_FIELD = "CGLIB$CONSTRUCTED";
+
+ private static final Type FACTORY =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.Factory");
+ private static final Type ILLEGAL_STATE_EXCEPTION =
+ TypeUtils.parseType("IllegalStateException");
+ private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
+ TypeUtils.parseType("IllegalArgumentException");
+ private static final Type THREAD_LOCAL =
+ TypeUtils.parseType("ThreadLocal");
+ private static final Type CALLBACK =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.Callback");
+ private static final Type CALLBACK_ARRAY =
+ Type.getType(Callback[].class);
+ private static final Signature CSTRUCT_NULL =
+ TypeUtils.parseConstructor("");
+ private static final Signature SET_THREAD_CALLBACKS =
+ new Signature(SET_THREAD_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
+ private static final Signature SET_STATIC_CALLBACKS =
+ new Signature(SET_STATIC_CALLBACKS_NAME, Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK_ARRAY });
+ private static final Signature MULTIARG_NEW_INSTANCE =
+ new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{
+ Constants.TYPE_CLASS_ARRAY,
+ Constants.TYPE_OBJECT_ARRAY,
+ CALLBACK_ARRAY,
+ });
+ private static final Signature SINGLE_NEW_INSTANCE =
+ new Signature("newInstance", Constants.TYPE_OBJECT, new Type[]{ CALLBACK });
+ private static final Signature SET_CALLBACK =
+ new Signature("setCallback", Type.VOID_TYPE, new Type[]{ Type.INT_TYPE, CALLBACK });
+ private static final Signature GET_CALLBACK =
+ new Signature("getCallback", CALLBACK, new Type[]{ Type.INT_TYPE });
+ private static final Signature SET_CALLBACKS =
+ new Signature("setCallbacks", Type.VOID_TYPE, new Type[]{ CALLBACK_ARRAY });
+ private static final Signature GET_CALLBACKS =
+ new Signature("getCallbacks", CALLBACK_ARRAY, new Type[0]);
+ private static final Signature THREAD_LOCAL_GET =
+ TypeUtils.parseSignature("Object get()");
+ private static final Signature THREAD_LOCAL_SET =
+ TypeUtils.parseSignature("void set(Object)");
+ private static final Signature BIND_CALLBACKS =
+ TypeUtils.parseSignature("void CGLIB$BIND_CALLBACKS(Object)");
+ private Class[] interfaces;
+ private CallbackFilter filter;
+ private Callback[] callbacks;
+ private Type[] callbackTypes;
+ private boolean classOnly;
+ private Class superclass;
+ private Class[] argumentTypes;
+ private Object[] arguments;
+ private boolean useFactory = true;
+ private Long serialVersionUID;
+ private boolean interceptDuringConstruction = true;
+ /**
+ * Create a new <code>Enhancer</code>. A new <code>Enhancer</code>
+ * object should be used for each generated object, and should not
+ * be shared across threads. To create additional instances of a
+ * generated class, use the <code>Factory</code> interface.
+ * @see Factory
+ */
+ public Enhancer() {
+ super(SOURCE);
+ }
+
+ /**
+ * Finds all of the methods that will be extended by an
+ * Enhancer-generated class using the specified superclass and
+ * interfaces. This can be useful in building a list of Callback
+ * objects. The methods are added to the end of the given list. Due
+ * to the subclassing nature of the classes generated by Enhancer,
+ * the methods are guaranteed to be non-static, non-final, and
+ * non-private. Each method signature will only occur once, even if
+ * it occurs in multiple classes.
+ * @param superclass the class that will be extended, or null
+ * @param interfaces the list of interfaces that will be implemented, or null
+ * @param methods the list into which to copy the applicable methods
+ */
+ public static void getMethods(Class superclass, Class[] interfaces, List methods)
+ {
+ getMethods(superclass, interfaces, methods, null, null);
+ }
+
+ private static void getMethods(Class superclass, Class[] interfaces, List methods, List interfaceMethods, Set forcePublic)
+ {
+ ReflectUtils.addAllMethods(superclass, methods);
+ List target = (interfaceMethods != null) ? interfaceMethods : methods;
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i] != Factory.class) {
+ ReflectUtils.addAllMethods(interfaces[i], target);
+ }
+ }
+ }
+ if (interfaceMethods != null) {
+ if (forcePublic != null) {
+ forcePublic.addAll(MethodWrapper.createSet(interfaceMethods));
+ }
+ methods.addAll(interfaceMethods);
+ }
+ CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_STATIC));
+ CollectionUtils.filter(methods, new VisibilityPredicate(superclass, true));
+ CollectionUtils.filter(methods, new DuplicatesPredicate());
+ CollectionUtils.filter(methods, new RejectModifierPredicate(Constants.ACC_FINAL));
+ }
+
+ /**
+ * Call this method to register the {@link Callback} array to use before
+ * creating a new instance of the generated class via reflection. If you are using
+ * an instance of <code>Enhancer</code> or the {@link Factory} interface to create
+ * new instances, this method is unnecessary. Its primary use is for when you want to
+ * cache and reuse a generated class yourself, and the generated class does
+ * <i>not</i> implement the {@link Factory} interface.
+ * <p>
+ * Note that this method only registers the callbacks on the current thread.
+ * If you want to register callbacks for instances created by multiple threads,
+ * use {@link #registerStaticCallbacks}.
+ * <p>
+ * The registered callbacks are overwritten and subsequently cleared
+ * when calling any of the <code>create</code> methods (such as
+ * {@link #create}), or any {@link Factory} <code>newInstance</code> method.
+ * Otherwise they are <i>not</i> cleared, and you should be careful to set them
+ * back to <code>null</code> after creating new instances via reflection if
+ * memory leakage is a concern.
+ * @param generatedClass a class previously created by {@link Enhancer}
+ * @param callbacks the array of callbacks to use when instances of the generated
+ * class are created
+ * @see #setUseFactory
+ */
+ public static void registerCallbacks(Class generatedClass, Callback[] callbacks) {
+ setThreadCallbacks(generatedClass, callbacks);
+ }
+
+ /**
+ * Similar to {@link #registerCallbacks}, but suitable for use
+ * when multiple threads will be creating instances of the generated class.
+ * The thread-level callbacks will always override the static callbacks.
+ * Static callbacks are never cleared.
+ * @param generatedClass a class previously created by {@link Enhancer}
+ * @param callbacks the array of callbacks to use when instances of the generated
+ * class are created
+ */
+ public static void registerStaticCallbacks(Class generatedClass, Callback[] callbacks) {
+ setCallbacksHelper(generatedClass, callbacks, SET_STATIC_CALLBACKS_NAME);
+ }
+
+ /**
+ * Determine if a class was generated using <code>Enhancer</code>.
+ * @param type any class
+ * @return whether the class was generated using <code>Enhancer</code>
+ */
+ public static boolean isEnhanced(Class type) {
+ try {
+ getCallbacksSetter(type, SET_THREAD_CALLBACKS_NAME);
+ return true;
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ private static void setThreadCallbacks(Class type, Callback[] callbacks) {
+ setCallbacksHelper(type, callbacks, SET_THREAD_CALLBACKS_NAME);
+ }
+
+ private static void setCallbacksHelper(Class type, Callback[] callbacks, String methodName) {
+ // TODO: optimize
+ try {
+ Method setter = getCallbacksSetter(type, methodName);
+ setter.invoke(null, new Object[]{ callbacks });
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException(type + " is not an enhanced class");
+ } catch (IllegalAccessException e) {
+ throw new CodeGenerationException(e);
+ } catch (InvocationTargetException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ private static Method getCallbacksSetter(Class type, String methodName) throws NoSuchMethodException {
+ return type.getDeclaredMethod(methodName, new Class[]{ Callback[].class });
+ }
+
+ /**
+ * Helper method to create an intercepted object.
+ * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
+ * instead of this static method.
+ * @param type class to extend or interface to implement
+ * @param callback the callback to use for all methods
+ */
+ public static Object create(Class type, Callback callback) {
+ Enhancer e = new Enhancer();
+ e.setSuperclass(type);
+ e.setCallback(callback);
+ return e.create();
+ }
+
+ /**
+ * Helper method to create an intercepted object.
+ * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
+ * instead of this static method.
+ * @param type class to extend or interface to implement
+ * @param interfaces array of interfaces to implement, or null
+ * @param callback the callback to use for all methods
+ */
+ public static Object create(Class superclass, Class interfaces[], Callback callback) {
+ Enhancer e = new Enhancer();
+ e.setSuperclass(superclass);
+ e.setInterfaces(interfaces);
+ e.setCallback(callback);
+ return e.create();
+ }
+
+ /**
+ * Helper method to create an intercepted object.
+ * For finer control over the generated instance, use a new instance of <code>Enhancer</code>
+ * instead of this static method.
+ * @param superclass class to extend or interface to implement
+ * @param interfaces array of interfaces to implement, or null
+ * @param filter the callback filter to use when generating a new class
+ * @param callbacks callback implementations to use for the enhanced object
+ */
+ public static Object create(Class superclass, Class[] interfaces, CallbackFilter filter, Callback[] callbacks) {
+ Enhancer e = new Enhancer();
+ e.setSuperclass(superclass);
+ e.setInterfaces(interfaces);
+ e.setCallbackFilter(filter);
+ e.setCallbacks(callbacks);
+ return e.create();
+ }
+
+ private static String getCallbackField(int index) {
+ return "CGLIB$CALLBACK_" + index;
+ }
+
+ /**
+ * Set the class which the generated class will extend. As a convenience,
+ * if the supplied superclass is actually an interface, <code>setInterfaces</code>
+ * will be called with the appropriate argument instead.
+ * A non-interface argument must not be declared as final, and must have an
+ * accessible constructor.
+ * @param superclass class to extend or interface to implement
+ * @see #setInterfaces(Class[])
+ */
+ public void setSuperclass(Class superclass) {
+ if (superclass != null && superclass.isInterface()) {
+ setInterfaces(new Class[]{ superclass });
+ } else if (superclass != null && superclass.equals(Object.class)) {
+ // affects choice of ClassLoader
+ this.superclass = null;
+ } else {
+ this.superclass = superclass;
+ }
+ }
+
+ /**
+ * Set the interfaces to implement. The <code>Factory</code> interface will
+ * always be implemented regardless of what is specified here.
+ * @param interfaces array of interfaces to implement, or null
+ * @see Factory
+ */
+ public void setInterfaces(Class[] interfaces) {
+ this.interfaces = interfaces;
+ }
+
+ /**
+ * Set the {@link CallbackFilter} used to map the generated class' methods
+ * to a particular callback index.
+ * New object instances will always use the same mapping, but may use different
+ * actual callback objects.
+ * @param filter the callback filter to use when generating a new class
+ * @see #setCallbacks
+ */
+ public void setCallbackFilter(CallbackFilter filter) {
+ this.filter = filter;
+ }
+
+ /**
+ * Set the single {@link Callback} to use.
+ * Ignored if you use {@link #createClass}.
+ * @param callback the callback to use for all methods
+ * @see #setCallbacks
+ */
+ public void setCallback(final Callback callback) {
+ setCallbacks(new Callback[]{ callback });
+ }
+
+ /**
+ * Set the array of callbacks to use.
+ * Ignored if you use {@link #createClass}.
+ * You must use a {@link CallbackFilter} to specify the index into this
+ * array for each method in the proxied class.
+ * @param callbacks the callback array
+ * @see #setCallbackFilter
+ * @see #setCallback
+ */
+ public void setCallbacks(Callback[] callbacks) {
+ if (callbacks != null && callbacks.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty");
+ }
+ this.callbacks = callbacks;
+ }
+
+ /**
+ * Set whether the enhanced object instances should implement
+ * the {@link Factory} interface.
+ * This was added for tools that need for proxies to be more
+ * indistinguishable from their targets. Also, in some cases it may
+ * be necessary to disable the <code>Factory</code> interface to
+ * prevent code from changing the underlying callbacks.
+ * @param useFactory whether to implement <code>Factory</code>; default is <code>true</code>
+ */
+ public void setUseFactory(boolean useFactory) {
+ this.useFactory = useFactory;
+ }
+
+ /**
+ * Set whether methods called from within the proxy's constructer
+ * will be intercepted. The default value is true. Unintercepted methods
+ * will call the method of the proxy's base class, if it exists.
+ * @param interceptDuringConstruction whether to intercept methods called from the constructor
+ */
+ public void setInterceptDuringConstruction(boolean interceptDuringConstruction) {
+ this.interceptDuringConstruction = interceptDuringConstruction;
+ }
+
+ /**
+ * Set the single type of {@link Callback} to use.
+ * This may be used instead of {@link #setCallback} when calling
+ * {@link #createClass}, since it may not be possible to have
+ * an array of actual callback instances.
+ * @param callbackType the type of callback to use for all methods
+ * @see #setCallbackTypes
+ */
+ public void setCallbackType(Class callbackType) {
+ setCallbackTypes(new Class[]{ callbackType });
+ }
+
+ /**
+ * Set the array of callback types to use.
+ * This may be used instead of {@link #setCallbacks} when calling
+ * {@link #createClass}, since it may not be possible to have
+ * an array of actual callback instances.
+ * You must use a {@link CallbackFilter} to specify the index into this
+ * array for each method in the proxied class.
+ * @param callbackTypes the array of callback types
+ */
+ public void setCallbackTypes(Class[] callbackTypes) {
+ if (callbackTypes != null && callbackTypes.length == 0) {
+ throw new IllegalArgumentException("Array cannot be empty");
+ }
+ this.callbackTypes = CallbackInfo.determineTypes(callbackTypes);
+ }
+
+ /**
+ * Generate a new class if necessary and uses the specified
+ * callbacks (if any) to create a new object instance.
+ * Uses the no-arg constructor of the superclass.
+ * @return a new instance
+ */
+ public Object create() {
+ classOnly = false;
+ argumentTypes = null;
+ return createHelper();
+ }
+
+ /**
+ * Generate a new class if necessary and uses the specified
+ * callbacks (if any) to create a new object instance.
+ * Uses the constructor of the superclass matching the <code>argumentTypes</code>
+ * parameter, with the given arguments.
+ * @param argumentTypes constructor signature
+ * @param arguments compatible wrapped arguments to pass to constructor
+ * @return a new instance
+ */
+ public Object create(Class[] argumentTypes, Object[] arguments) {
+ classOnly = false;
+ if (argumentTypes == null || arguments == null || argumentTypes.length != arguments.length) {
+ throw new IllegalArgumentException("Arguments must be non-null and of equal length");
+ }
+ this.argumentTypes = argumentTypes;
+ this.arguments = arguments;
+ return createHelper();
+ }
+
+ /**
+ * Generate a new class if necessary and return it without creating a new instance.
+ * This ignores any callbacks that have been set.
+ * To create a new instance you will have to use reflection, and methods
+ * called during the constructor will not be intercepted. To avoid this problem,
+ * use the multi-arg <code>create</code> method.
+ * @see #create(Class[], Object[])
+ */
+ public Class createClass() {
+ classOnly = true;
+ return (Class)createHelper();
+ }
+
+ /**
+ * Insert a static serialVersionUID field into the generated class.
+ * @param sUID the field value, or null to avoid generating field.
+ */
+ public void setSerialVersionUID(Long sUID) {
+ serialVersionUID = sUID;
+ }
+
+ private void validate() {
+ if (classOnly ^ (callbacks == null)) {
+ if (classOnly) {
+ throw new IllegalStateException("createClass does not accept callbacks");
+ } else {
+ throw new IllegalStateException("Callbacks are required");
+ }
+ }
+ if (classOnly && (callbackTypes == null)) {
+ throw new IllegalStateException("Callback types are required");
+ }
+ if (callbacks != null && callbackTypes != null) {
+ if (callbacks.length != callbackTypes.length) {
+ throw new IllegalStateException("Lengths of callback and callback types array must be the same");
+ }
+ Type[] check = CallbackInfo.determineTypes(callbacks);
+ for (int i = 0; i < check.length; i++) {
+ if (!check[i].equals(callbackTypes[i])) {
+ throw new IllegalStateException("Callback " + check[i] + " is not assignable to " + callbackTypes[i]);
+ }
+ }
+ } else if (callbacks != null) {
+ callbackTypes = CallbackInfo.determineTypes(callbacks);
+ }
+ if (filter == null) {
+ if (callbackTypes.length > 1) {
+ throw new IllegalStateException("Multiple callback types possible but no filter specified");
+ }
+ filter = ALL_ZERO;
+ }
+ if (interfaces != null) {
+ for (int i = 0; i < interfaces.length; i++) {
+ if (interfaces[i] == null) {
+ throw new IllegalStateException("Interfaces cannot be null");
+ }
+ if (!interfaces[i].isInterface()) {
+ throw new IllegalStateException(interfaces[i] + " is not an interface");
+ }
+ }
+ }
+ }
+
+ private Object createHelper() {
+ validate();
+ if (superclass != null) {
+ setNamePrefix(superclass.getName());
+ } else if (interfaces != null) {
+ setNamePrefix(interfaces[ReflectUtils.findPackageProtected(interfaces)].getName());
+ }
+ return super.create(KEY_FACTORY.newInstance((superclass != null) ? superclass.getName() : null,
+ ReflectUtils.getNames(interfaces),
+ filter,
+ callbackTypes,
+ useFactory,
+ interceptDuringConstruction,
+ serialVersionUID));
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ if (superclass != null) {
+ return superclass.getClassLoader();
+ } else if (interfaces != null) {
+ return interfaces[0].getClassLoader();
+ } else {
+ return null;
+ }
+ }
+
+ private Signature rename(Signature sig, int index) {
+ return new Signature("CGLIB$" + sig.getName() + "$" + index,
+ sig.getDescriptor());
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ Class sc = (superclass == null) ? Object.class : superclass;
+
+ if (TypeUtils.isFinal(sc.getModifiers()))
+ throw new IllegalArgumentException("Cannot subclass final class " + sc);
+ List constructors = new ArrayList(Arrays.asList(sc.getDeclaredConstructors()));
+ filterConstructors(sc, constructors);
+
+ // Order is very important: must add superclass, then
+ // its superclass chain, then each interface and
+ // its superinterfaces.
+ List actualMethods = new ArrayList();
+ List interfaceMethods = new ArrayList();
+ final Set forcePublic = new HashSet();
+ getMethods(sc, interfaces, actualMethods, interfaceMethods, forcePublic);
+
+ List methods = CollectionUtils.transform(actualMethods, new Transformer() {
+ public Object transform(Object value) {
+ Method method = (Method)value;
+ int modifiers = Constants.ACC_FINAL
+ | (method.getModifiers()
+ & ~Constants.ACC_ABSTRACT
+ & ~Constants.ACC_NATIVE
+ & ~Constants.ACC_SYNCHRONIZED);
+ if (forcePublic.contains(MethodWrapper.create(method))) {
+ modifiers = (modifiers & ~Constants.ACC_PROTECTED) | Constants.ACC_PUBLIC;
+ }
+ return ReflectUtils.getMethodInfo(method, modifiers);
+ }
+ });
+
+ ClassEmitter e = new ClassEmitter(v);
+ e.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ Type.getType(sc),
+ (useFactory ?
+ TypeUtils.add(TypeUtils.getTypes(interfaces), FACTORY) :
+ TypeUtils.getTypes(interfaces)),
+ Constants.SOURCE_FILE);
+ List constructorInfo = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
+
+ e.declare_field(Constants.ACC_PRIVATE, BOUND_FIELD, Type.BOOLEAN_TYPE, null);
+ if (!interceptDuringConstruction) {
+ e.declare_field(Constants.ACC_PRIVATE, CONSTRUCTED_FIELD, Type.BOOLEAN_TYPE, null);
+ }
+ e.declare_field(Constants.PRIVATE_FINAL_STATIC, THREAD_CALLBACKS_FIELD, THREAD_LOCAL, null);
+ e.declare_field(Constants.PRIVATE_FINAL_STATIC, STATIC_CALLBACKS_FIELD, CALLBACK_ARRAY, null);
+ if (serialVersionUID != null) {
+ e.declare_field(Constants.PRIVATE_FINAL_STATIC, Constants.SUID_FIELD_NAME, Type.LONG_TYPE, serialVersionUID);
+ }
+
+ for (int i = 0; i < callbackTypes.length; i++) {
+ e.declare_field(Constants.ACC_PRIVATE, getCallbackField(i), callbackTypes[i], null);
+ }
+
+ emitMethods(e, methods, actualMethods);
+ emitConstructors(e, constructorInfo);
+ emitSetThreadCallbacks(e);
+ emitSetStaticCallbacks(e);
+ emitBindCallbacks(e);
+
+ if (useFactory) {
+ int[] keys = getCallbackKeys();
+ emitNewInstanceCallbacks(e);
+ emitNewInstanceCallback(e);
+ emitNewInstanceMultiarg(e, constructorInfo);
+ emitGetCallback(e, keys);
+ emitSetCallback(e, keys);
+ emitGetCallbacks(e);
+ emitSetCallbacks(e);
+ }
+
+ e.end_class();
+ }
+
+ /**
+ * Filter the list of constructors from the superclass. The
+ * constructors which remain will be included in the generated
+ * class. The default implementation is to filter out all private
+ * constructors, but subclasses may extend Enhancer to override this
+ * behavior.
+ * @param sc the superclass
+ * @param constructors the list of all declared constructors from the superclass
+ * @throws IllegalArgumentException if there are no non-private constructors
+ */
+ protected void filterConstructors(Class sc, List constructors) {
+ CollectionUtils.filter(constructors, new VisibilityPredicate(sc, true));
+ if (constructors.size() == 0)
+ throw new IllegalArgumentException("No visible constructors in " + sc);
+ }
+
+ protected Object firstInstance(Class type) throws Exception {
+ if (classOnly) {
+ return type;
+ } else {
+ return createUsingReflection(type);
+ }
+ }
+
+ protected Object nextInstance(Object instance) {
+ Class protoclass = (instance instanceof Class) ? (Class)instance : instance.getClass();
+ if (classOnly) {
+ return protoclass;
+ } else if (instance instanceof Factory) {
+ if (argumentTypes != null) {
+ return ((Factory)instance).newInstance(argumentTypes, arguments, callbacks);
+ } else {
+ return ((Factory)instance).newInstance(callbacks);
+ }
+ } else {
+ return createUsingReflection(protoclass);
+ }
+ }
+
+ private Object createUsingReflection(Class type) {
+ setThreadCallbacks(type, callbacks);
+ try{
+
+ if (argumentTypes != null) {
+
+ return ReflectUtils.newInstance(type, argumentTypes, arguments);
+
+ } else {
+
+ return ReflectUtils.newInstance(type);
+
+ }
+ }finally{
+ // clear thread callbacks to allow them to be gc'd
+ setThreadCallbacks(type, null);
+ }
+ }
+
+ private void emitConstructors(ClassEmitter ce, List constructors) {
+ boolean seenNull = false;
+ for (Iterator it = constructors.iterator(); it.hasNext();) {
+ MethodInfo constructor = (MethodInfo)it.next();
+ CodeEmitter e = EmitUtils.begin_method(ce, constructor, Constants.ACC_PUBLIC);
+ e.load_this();
+ e.dup();
+ e.load_args();
+ Signature sig = constructor.getSignature();
+ seenNull = seenNull || sig.getDescriptor().equals("()V");
+ e.super_invoke_constructor(sig);
+ e.invoke_static_this(BIND_CALLBACKS);
+ if (!interceptDuringConstruction) {
+ e.load_this();
+ e.push(1);
+ e.putfield(CONSTRUCTED_FIELD);
+ }
+ e.return_value();
+ e.end_method();
+ }
+ if (!classOnly && !seenNull && arguments == null)
+ throw new IllegalArgumentException("Superclass has no null constructors but no arguments were given");
+ }
+
+ private int[] getCallbackKeys() {
+ int[] keys = new int[callbackTypes.length];
+ for (int i = 0; i < callbackTypes.length; i++) {
+ keys[i] = i;
+ }
+ return keys;
+ }
+
+ private void emitGetCallback(ClassEmitter ce, int[] keys) {
+ final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACK, null);
+ e.load_this();
+ e.invoke_static_this(BIND_CALLBACKS);
+ e.load_this();
+ e.load_arg(0);
+ e.process_switch(keys, new ProcessSwitchCallback() {
+ public void processCase(int key, Label end) {
+ e.getfield(getCallbackField(key));
+ e.goTo(end);
+ }
+ public void processDefault() {
+ e.pop(); // stack height
+ e.aconst_null();
+ }
+ });
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitSetCallback(ClassEmitter ce, int[] keys) {
+ final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACK, null);
+ e.load_arg(0);
+ e.process_switch(keys, new ProcessSwitchCallback() {
+ public void processCase(int key, Label end) {
+ e.load_this();
+ e.load_arg(1);
+ e.checkcast(callbackTypes[key]);
+ e.putfield(getCallbackField(key));
+ e.goTo(end);
+ }
+ public void processDefault() {
+ // TODO: error?
+ }
+ });
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitSetCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SET_CALLBACKS, null);
+ e.load_this();
+ e.load_arg(0);
+ for (int i = 0; i < callbackTypes.length; i++) {
+ e.dup2();
+ e.aaload(i);
+ e.checkcast(callbackTypes[i]);
+ e.putfield(getCallbackField(i));
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitGetCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, GET_CALLBACKS, null);
+ e.load_this();
+ e.invoke_static_this(BIND_CALLBACKS);
+ e.load_this();
+ e.push(callbackTypes.length);
+ e.newarray(CALLBACK);
+ for (int i = 0; i < callbackTypes.length; i++) {
+ e.dup();
+ e.push(i);
+ e.load_this();
+ e.getfield(getCallbackField(i));
+ e.aastore();
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitNewInstanceCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
+ e.load_arg(0);
+ e.invoke_static_this(SET_THREAD_CALLBACKS);
+ emitCommonNewInstance(e);
+ }
+
+ private void emitCommonNewInstance(CodeEmitter e) {
+ e.new_instance_this();
+ e.dup();
+ e.invoke_constructor_this();
+ e.aconst_null();
+ e.invoke_static_this(SET_THREAD_CALLBACKS);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitNewInstanceCallback(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, SINGLE_NEW_INSTANCE, null);
+ switch (callbackTypes.length) {
+ case 0:
+ // TODO: make sure Callback is null
+ break;
+ case 1:
+ // for now just make a new array; TODO: optimize
+ e.push(1);
+ e.newarray(CALLBACK);
+ e.dup();
+ e.push(0);
+ e.load_arg(0);
+ e.aastore();
+ e.invoke_static_this(SET_THREAD_CALLBACKS);
+ break;
+ default:
+ e.throw_exception(ILLEGAL_STATE_EXCEPTION, "More than one callback object required");
+ }
+ emitCommonNewInstance(e);
+ }
+
+ private void emitNewInstanceMultiarg(ClassEmitter ce, List constructors) {
+ final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, MULTIARG_NEW_INSTANCE, null);
+ e.load_arg(2);
+ e.invoke_static_this(SET_THREAD_CALLBACKS);
+ e.new_instance_this();
+ e.dup();
+ e.load_arg(0);
+ EmitUtils.constructor_switch(e, constructors, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ MethodInfo constructor = (MethodInfo)key;
+ Type types[] = constructor.getSignature().getArgumentTypes();
+ for (int i = 0; i < types.length; i++) {
+ e.load_arg(1);
+ e.push(i);
+ e.aaload();
+ e.unbox(types[i]);
+ }
+ e.invoke_constructor_this(constructor.getSignature());
+ e.goTo(end);
+ }
+ public void processDefault() {
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Constructor not found");
+ }
+ });
+ e.aconst_null();
+ e.invoke_static_this(SET_THREAD_CALLBACKS);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitMethods(final ClassEmitter ce, List methods, List actualMethods) {
+ CallbackGenerator[] generators = CallbackInfo.getGenerators(callbackTypes);
+
+ Map groups = new HashMap();
+ final Map indexes = new HashMap();
+ final Map originalModifiers = new HashMap();
+ final Map positions = CollectionUtils.getIndexMap(methods);
+
+ Iterator it1 = methods.iterator();
+ Iterator it2 = (actualMethods != null) ? actualMethods.iterator() : null;
+
+ while (it1.hasNext()) {
+ MethodInfo method = (MethodInfo)it1.next();
+ Method actualMethod = (it2 != null) ? (Method)it2.next() : null;
+ int index = filter.accept(actualMethod, actualMethods);
+ if (index >= callbackTypes.length) {
+ throw new IllegalArgumentException("Callback filter returned an index that is too large: " + index);
+ }
+ originalModifiers.put(method, new Integer((actualMethod != null) ? actualMethod.getModifiers() : method.getModifiers()));
+ indexes.put(method, new Integer(index));
+ List group = (List)groups.get(generators[index]);
+ if (group == null) {
+ groups.put(generators[index], group = new ArrayList(methods.size()));
+ }
+ group.add(method);
+ }
+
+ Set seenGen = new HashSet();
+ CodeEmitter se = ce.getStaticHook();
+ se.new_instance(THREAD_LOCAL);
+ se.dup();
+ se.invoke_constructor(THREAD_LOCAL, CSTRUCT_NULL);
+ se.putfield(THREAD_CALLBACKS_FIELD);
+
+ final Object[] state = new Object[1];
+ CallbackGenerator.Context context = new CallbackGenerator.Context() {
+ public ClassLoader getClassLoader() {
+ return Enhancer.this.getClassLoader();
+ }
+ public int getOriginalModifiers(MethodInfo method) {
+ return ((Integer)originalModifiers.get(method)).intValue();
+ }
+ public int getIndex(MethodInfo method) {
+ return ((Integer)indexes.get(method)).intValue();
+ }
+ public void emitCallback(CodeEmitter e, int index) {
+ emitCurrentCallback(e, index);
+ }
+ public Signature getImplSignature(MethodInfo method) {
+ return rename(method.getSignature(), ((Integer)positions.get(method)).intValue());
+ }
+ public CodeEmitter beginMethod(ClassEmitter ce, MethodInfo method) {
+ CodeEmitter e = EmitUtils.begin_method(ce, method);
+ if (!interceptDuringConstruction &&
+ !TypeUtils.isAbstract(method.getModifiers())) {
+ Label constructed = e.make_label();
+ e.load_this();
+ e.getfield(CONSTRUCTED_FIELD);
+ e.if_jump(e.NE, constructed);
+ e.load_this();
+ e.load_args();
+ e.super_invoke();
+ e.return_value();
+ e.mark(constructed);
+ }
+ return e;
+ }
+ };
+ for (int i = 0; i < callbackTypes.length; i++) {
+ CallbackGenerator gen = generators[i];
+ if (!seenGen.contains(gen)) {
+ seenGen.add(gen);
+ final List fmethods = (List)groups.get(gen);
+ if (fmethods != null) {
+ try {
+ gen.generate(ce, context, fmethods);
+ gen.generateStatic(se, context, fmethods);
+ } catch (RuntimeException x) {
+ throw x;
+ } catch (Exception x) {
+ throw new CodeGenerationException(x);
+ }
+ }
+ }
+ }
+ se.return_value();
+ se.end_method();
+ }
+
+ private void emitSetThreadCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+ SET_THREAD_CALLBACKS,
+ null);
+ e.getfield(THREAD_CALLBACKS_FIELD);
+ e.load_arg(0);
+ e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_SET);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitSetStaticCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+ SET_STATIC_CALLBACKS,
+ null);
+ e.load_arg(0);
+ e.putfield(STATIC_CALLBACKS_FIELD);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void emitCurrentCallback(CodeEmitter e, int index) {
+ e.load_this();
+ e.getfield(getCallbackField(index));
+ e.dup();
+ Label end = e.make_label();
+ e.ifnonnull(end);
+ e.pop(); // stack height
+ e.load_this();
+ e.invoke_static_this(BIND_CALLBACKS);
+ e.load_this();
+ e.getfield(getCallbackField(index));
+ e.mark(end);
+ }
+
+ private void emitBindCallbacks(ClassEmitter ce) {
+ CodeEmitter e = ce.begin_method(Constants.PRIVATE_FINAL_STATIC,
+ BIND_CALLBACKS,
+ null);
+ Local me = e.make_local();
+ e.load_arg(0);
+ e.checkcast_this();
+ e.store_local(me);
+
+ Label end = e.make_label();
+ e.load_local(me);
+ e.getfield(BOUND_FIELD);
+ e.if_jump(e.NE, end);
+ e.load_local(me);
+ e.push(1);
+ e.putfield(BOUND_FIELD);
+
+ e.getfield(THREAD_CALLBACKS_FIELD);
+ e.invoke_virtual(THREAD_LOCAL, THREAD_LOCAL_GET);
+ e.dup();
+ Label found_callback = e.make_label();
+ e.ifnonnull(found_callback);
+ e.pop();
+
+ e.getfield(STATIC_CALLBACKS_FIELD);
+ e.dup();
+ e.ifnonnull(found_callback);
+ e.pop();
+ e.goTo(end);
+
+ e.mark(found_callback);
+ e.checkcast(CALLBACK_ARRAY);
+ e.load_local(me);
+ e.swap();
+ for (int i = callbackTypes.length - 1; i >= 0; i--) {
+ if (i != 0) {
+ e.dup2();
+ }
+ e.aaload(i);
+ e.checkcast(callbackTypes[i]);
+ e.putfield(getCallbackField(i));
+ }
+
+ e.mark(end);
+ e.return_value();
+ e.end_method();
+ }
+
+ /** Internal interface, only public due to ClassLoader issues. */
+ public interface EnhancerKey {
+ public Object newInstance(String type,
+ String[] interfaces,
+ CallbackFilter filter,
+ Type[] callbackTypes,
+ boolean useFactory,
+ boolean interceptDuringConstruction,
+ Long serialVersionUID);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Factory.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Factory.java
new file mode 100644
index 0000000..a6db06c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Factory.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * All enhanced instances returned by the {@link Enhancer} class implement this interface.
+ * Using this interface for new instances is faster than going through the <code>Enhancer</code>
+ * interface or using reflection. In addition, to intercept methods called during
+ * object construction you <b>must</b> use these methods instead of reflection.
+ * @author Juozas Baliuka <a href="mailto:baliuka at mwm.lt">baliuka at mwm.lt</a>
+ * @version $Id: Factory.java,v 1.13 2004/06/24 21:15:20 herbyderby Exp $
+ */
+public interface Factory {
+ /**
+ * Creates new instance of the same type, using the no-arg constructor.
+ * The class of this object must have been created using a single Callback type.
+ * If multiple callbacks are required an exception will be thrown.
+ * @param callback the new interceptor to use
+ * @return new instance of the same type
+ */
+ Object newInstance(Callback callback);
+
+ /**
+ * Creates new instance of the same type, using the no-arg constructor.
+ * @param callbacks the new callbacks(s) to use
+ * @return new instance of the same type
+ */
+ Object newInstance(Callback[] callbacks);
+
+ /**
+ * Creates a new instance of the same type, using the constructor
+ * matching the given signature.
+ * @param types the constructor argument types
+ * @param args the constructor arguments
+ * @param callbacks the new interceptor(s) to use
+ * @return new instance of the same type
+ */
+ Object newInstance(Class[] types, Object[] args, Callback[] callbacks);
+
+ /**
+ * Return the <code>Callback</code> implementation at the specified index.
+ * @param index the callback index
+ * @return the callback implementation
+ */
+ Callback getCallback(int index);
+
+ /**
+ * Set the callback for this object for the given type.
+ * @param index the callback index to replace
+ * @param callback the new callback
+ */
+ void setCallback(int index, Callback callback);
+
+ /**
+ * Get the current set of callbacks for ths object.
+ * @return a new array instance
+ */
+ Callback[] getCallbacks();
+
+ /**
+ * Replace all of the callbacks for this object at once.
+ * @param callbacks the new callbacks(s) to use
+ */
+ void setCallbacks(Callback[] callbacks);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValue.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValue.java
new file mode 100644
index 0000000..b2aba1c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValue.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * {@link Enhancer} callback that simply returns the value to return
+ * from the proxied method. No information about what method
+ * is being called is available to the callback, and the type of
+ * the returned object must be compatible with the return type of
+ * the proxied method. This makes this callback primarily useful
+ * for forcing a particular method (through the use of a {@link CallbackFilter}
+ * to return a fixed value with little overhead.
+ */
+public interface FixedValue extends Callback {
+ /**
+ * Return the object which the original method invocation should
+ * return. This method is called for <b>every</b> method invocation.
+ * @return an object matching the type of the return value for every
+ * method this callback is mapped to
+ */
+ Object loadObject() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValueGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValueGenerator.java
new file mode 100644
index 0000000..b929aa1
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/FixedValueGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.Iterator;
+import java.util.List;
+
+class FixedValueGenerator implements CallbackGenerator {
+ public static final FixedValueGenerator INSTANCE = new FixedValueGenerator();
+ private static final Type FIXED_VALUE =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.FixedValue");
+ private static final Signature LOAD_OBJECT =
+ TypeUtils.parseSignature("Object loadObject()");
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ CodeEmitter e = context.beginMethod(ce, method);
+ context.emitCallback(e, context.getIndex(method));
+ e.invoke_interface(FIXED_VALUE, LOAD_OBJECT);
+ e.unbox_or_zero(e.getReturnType());
+ e.return_value();
+ e.end_method();
+ }
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) { }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InterfaceMaker.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InterfaceMaker.java
new file mode 100644
index 0000000..2322fd0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InterfaceMaker.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Generates new interfaces at runtime.
+ * By passing a generated interface to the Enhancer's list of interfaces to
+ * implement, you can make your enhanced classes handle an arbitrary set
+ * of method signatures.
+ * @author Chris Nokleberg
+ * @version $Id: InterfaceMaker.java,v 1.4 2006/03/05 02:43:19 herbyderby Exp $
+ */
+public class InterfaceMaker extends AbstractClassGenerator
+{
+ private static final Source SOURCE = new Source(InterfaceMaker.class.getName());
+ private Map signatures = new HashMap();
+
+ /**
+ * Create a new <code>InterfaceMaker</code>. A new <code>InterfaceMaker</code>
+ * object should be used for each generated interface, and should not
+ * be shared across threads.
+ */
+ public InterfaceMaker() {
+ super(SOURCE);
+ }
+
+ /**
+ * Add a method signature to the interface.
+ * @param sig the method signature to add to the interface
+ * @param exceptions an array of exception types to declare for the method
+ */
+ public void add(Signature sig, Type[] exceptions) {
+ signatures.put(sig, exceptions);
+ }
+
+ /**
+ * Add a method signature to the interface. The method modifiers are ignored,
+ * since interface methods are by definition abstract and public.
+ * @param method the method to add to the interface
+ */
+ public void add(Method method) {
+ add(ReflectUtils.getSignature(method),
+ ReflectUtils.getExceptionTypes(method));
+ }
+
+ /**
+ * Add all the public methods in the specified class.
+ * Methods from superclasses are included, except for methods declared in the base
+ * Object class (e.g. <code>getClass</code>, <code>equals</code>, <code>hashCode</code>).
+ * @param clazz the class containing the methods to add to the interface
+ */
+ public void add(Class clazz) {
+ Method[] methods = clazz.getMethods();
+ for (int i = 0; i < methods.length; i++) {
+ Method m = methods[i];
+ if (!m.getDeclaringClass().getName().equals("java.lang.Object")) {
+ add(m);
+ }
+ }
+ }
+
+ /**
+ * Create an interface using the current set of method signatures.
+ */
+ public Class create() {
+ setUseCache(false);
+ return (Class)super.create(this);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return null;
+ }
+
+ protected Object firstInstance(Class type) {
+ return type;
+ }
+
+ protected Object nextInstance(Object instance) {
+ throw new IllegalStateException("InterfaceMaker does not cache");
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC | Constants.ACC_INTERFACE,
+ getClassName(),
+ null,
+ null,
+ Constants.SOURCE_FILE);
+ for (Iterator it = signatures.keySet().iterator(); it.hasNext();) {
+ Signature sig = (Signature)it.next();
+ Type[] exceptions = (Type[])signatures.get(sig);
+ ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_ABSTRACT,
+ sig,
+ exceptions).end_method();
+ }
+ ce.end_class();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandler.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandler.java
new file mode 100644
index 0000000..ea5ff8f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandler.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import java.lang.reflect.Method;
+
+/**
+ * {@link java.lang.reflect.InvocationHandler} replacement (unavailable under JDK 1.2).
+ * This callback type is primarily for use by the {@link Proxy} class but
+ * may be used with {@link Enhancer} as well.
+ * @author Neeme Praks <a href="mailto:neeme at apache.org">neeme at apache.org</a>
+ * @version $Id: InvocationHandler.java,v 1.3 2004/06/24 21:15:20 herbyderby Exp $
+ */
+public interface InvocationHandler
+extends Callback
+{
+ /**
+ * @see java.lang.reflect.InvocationHandler#invoke(Object, Method, Object)
+ */
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandlerGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandlerGenerator.java
new file mode 100644
index 0000000..e13fda0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/InvocationHandlerGenerator.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.Block;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.Iterator;
+import java.util.List;
+
+class InvocationHandlerGenerator
+implements CallbackGenerator
+{
+ public static final InvocationHandlerGenerator INSTANCE = new InvocationHandlerGenerator();
+
+ private static final Type INVOCATION_HANDLER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.InvocationHandler");
+ private static final Type UNDECLARED_THROWABLE_EXCEPTION =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.UndeclaredThrowableException");
+ private static final Type METHOD =
+ TypeUtils.parseType("java.lang.reflect.Method");
+ private static final Signature INVOKE =
+ TypeUtils.parseSignature("Object invoke(Object, java.lang.reflect.Method, Object[])");
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ Signature impl = context.getImplSignature(method);
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, impl.getName(), METHOD, null);
+
+ CodeEmitter e = context.beginMethod(ce, method);
+ Block handler = e.begin_block();
+ context.emitCallback(e, context.getIndex(method));
+ e.load_this();
+ e.getfield(impl.getName());
+ e.create_arg_array();
+ e.invoke_interface(INVOCATION_HANDLER, INVOKE);
+ e.unbox(method.getSignature().getReturnType());
+ e.return_value();
+ handler.end();
+ EmitUtils.wrap_undeclared_throwable(e, handler, method.getExceptionTypes(), UNDECLARED_THROWABLE_EXCEPTION);
+ e.end_method();
+ }
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) {
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ EmitUtils.load_method(e, method);
+ e.putfield(context.getImplSignature(method).getName());
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoader.java
new file mode 100644
index 0000000..c71e704
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoader.java
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * Lazy-loading {@link Enhancer} callback.
+ */
+public interface LazyLoader extends Callback {
+ /**
+ * Return the object which the original method invocation should be
+ * dispatched. Called as soon as the first lazily-loaded method in
+ * the enhanced instance is invoked. The same object is then used
+ * for every future method call to the proxy instance.
+ * @return an object that can invoke the method
+ */
+ Object loadObject() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoaderGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoaderGenerator.java
new file mode 100644
index 0000000..a0ecf31
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/LazyLoaderGenerator.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+class LazyLoaderGenerator implements CallbackGenerator {
+ public static final LazyLoaderGenerator INSTANCE = new LazyLoaderGenerator();
+
+ private static final Signature LOAD_OBJECT =
+ TypeUtils.parseSignature("Object loadObject()");
+ private static final Type LAZY_LOADER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.LazyLoader");
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ Set indexes = new HashSet();
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ if (TypeUtils.isProtected(method.getModifiers())) {
+ // ignore protected methods
+ } else {
+ int index = context.getIndex(method);
+ indexes.add(new Integer(index));
+ CodeEmitter e = context.beginMethod(ce, method);
+ e.load_this();
+ e.dup();
+ e.invoke_virtual_this(loadMethod(index));
+ e.checkcast(method.getClassInfo().getType());
+ e.load_args();
+ e.invoke(method);
+ e.return_value();
+ e.end_method();
+ }
+ }
+
+ for (Iterator it = indexes.iterator(); it.hasNext();) {
+ int index = ((Integer)it.next()).intValue();
+
+ String delegate = "CGLIB$LAZY_LOADER_" + index;
+ ce.declare_field(Constants.ACC_PRIVATE, delegate, Constants.TYPE_OBJECT, null);
+
+ CodeEmitter e = ce.begin_method(Constants.ACC_PRIVATE |
+ Constants.ACC_SYNCHRONIZED |
+ Constants.ACC_FINAL,
+ loadMethod(index),
+ null);
+ e.load_this();
+ e.getfield(delegate);
+ e.dup();
+ Label end = e.make_label();
+ e.ifnonnull(end);
+ e.pop();
+ e.load_this();
+ context.emitCallback(e, index);
+ e.invoke_interface(LAZY_LOADER, LOAD_OBJECT);
+ e.dup_x1();
+ e.putfield(delegate);
+ e.mark(end);
+ e.return_value();
+ e.end_method();
+
+ }
+ }
+
+ private Signature loadMethod(int index) {
+ return new Signature("CGLIB$LOAD_PRIVATE_" + index,
+ Constants.TYPE_OBJECT,
+ Constants.TYPES_EMPTY);
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) { }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptor.java
new file mode 100644
index 0000000..827f5df
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptor.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * General-purpose {@link Enhancer} callback which provides for "around advice".
+ * @author Juozas Baliuka <a href="mailto:baliuka at mwm.lt">baliuka at mwm.lt</a>
+ * @version $Id: MethodInterceptor.java,v 1.8 2004/06/24 21:15:20 herbyderby Exp $
+ */
+public interface MethodInterceptor
+extends Callback
+{
+ /**
+ * All generated proxied methods call this method instead of the original method.
+ * The original method may either be invoked by normal reflection using the Method object,
+ * or by using the MethodProxy (faster).
+ * @param obj "this", the enhanced object
+ * @param method intercepted Method
+ * @param args argument array; primitive types are wrapped
+ * @param proxy used to invoke super (non-intercepted method); may be called
+ * as many times as needed
+ * @throws Throwable any exception may be thrown; if so, super method will not be invoked
+ * @return any value compatible with the signature of the proxied method. Method returning void will ignore this value.
+ * @see MethodProxy
+ */
+ public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
+ MethodProxy proxy) throws Throwable;
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptorGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptorGenerator.java
new file mode 100644
index 0000000..387fc76
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodInterceptorGenerator.java
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CollectionUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.Transformer;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+class MethodInterceptorGenerator
+implements CallbackGenerator
+{
+ public static final MethodInterceptorGenerator INSTANCE = new MethodInterceptorGenerator();
+
+ static final String EMPTY_ARGS_NAME = "CGLIB$emptyArgs";
+ static final String FIND_PROXY_NAME = "CGLIB$findMethodProxy";
+ static final Class[] FIND_PROXY_TYPES = { Signature.class };
+
+ private static final Type ABSTRACT_METHOD_ERROR =
+ TypeUtils.parseType("AbstractMethodError");
+ private static final Type METHOD =
+ TypeUtils.parseType("java.lang.reflect.Method");
+ private static final Type REFLECT_UTILS =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils");
+ private static final Type METHOD_PROXY =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.MethodProxy");
+ private static final Type METHOD_INTERCEPTOR =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.MethodInterceptor");
+ private static final Signature GET_DECLARED_METHODS =
+ TypeUtils.parseSignature("java.lang.reflect.Method[] getDeclaredMethods()");
+ private static final Signature GET_DECLARING_CLASS =
+ TypeUtils.parseSignature("Class getDeclaringClass()");
+ private static final Signature FIND_METHODS =
+ TypeUtils.parseSignature("java.lang.reflect.Method[] findMethods(String[], java.lang.reflect.Method[])");
+ private static final Signature MAKE_PROXY =
+ new Signature("create", METHOD_PROXY, new Type[]{
+ Constants.TYPE_CLASS,
+ Constants.TYPE_CLASS,
+ Constants.TYPE_STRING,
+ Constants.TYPE_STRING,
+ Constants.TYPE_STRING
+ });
+ private static final Signature INTERCEPT =
+ new Signature("intercept", Constants.TYPE_OBJECT, new Type[]{
+ Constants.TYPE_OBJECT,
+ METHOD,
+ Constants.TYPE_OBJECT_ARRAY,
+ METHOD_PROXY
+ });
+ private static final Signature FIND_PROXY =
+ new Signature(FIND_PROXY_NAME, METHOD_PROXY, new Type[]{ Constants.TYPE_SIGNATURE });
+ private static final Signature TO_STRING =
+ TypeUtils.parseSignature("String toString()");
+ private static final Transformer METHOD_TO_CLASS = new Transformer(){
+ public Object transform(Object value) {
+ return ((MethodInfo)value).getClassInfo();
+ }
+ };
+ private static final Signature CSTRUCT_SIGNATURE =
+ TypeUtils.parseConstructor("String, String");
+
+ private static void superHelper(CodeEmitter e, MethodInfo method)
+ {
+ if (TypeUtils.isAbstract(method.getModifiers())) {
+ e.throw_exception(ABSTRACT_METHOD_ERROR, method.toString() + " is abstract" );
+ } else {
+ e.load_this();
+ e.load_args();
+ e.super_invoke(method.getSignature());
+ }
+ }
+
+ private String getMethodField(Signature impl) {
+ return impl.getName() + "$Method";
+ }
+
+ private String getMethodProxyField(Signature impl) {
+ return impl.getName() + "$Proxy";
+ }
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ Map sigMap = new HashMap();
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ Signature sig = method.getSignature();
+ Signature impl = context.getImplSignature(method);
+
+ String methodField = getMethodField(impl);
+ String methodProxyField = getMethodProxyField(impl);
+
+ sigMap.put(sig.toString(), methodProxyField);
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodField, METHOD, null);
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, methodProxyField, METHOD_PROXY, null);
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, EMPTY_ARGS_NAME, Constants.TYPE_OBJECT_ARRAY, null);
+ CodeEmitter e;
+
+ // access method
+ e = ce.begin_method(Constants.ACC_FINAL,
+ impl,
+ method.getExceptionTypes());
+ superHelper(e, method);
+ e.return_value();
+ e.end_method();
+
+ // around method
+ e = context.beginMethod(ce, method);
+ Label nullInterceptor = e.make_label();
+ context.emitCallback(e, context.getIndex(method));
+ e.dup();
+ e.ifnull(nullInterceptor);
+
+ e.load_this();
+ e.getfield(methodField);
+
+ if (sig.getArgumentTypes().length == 0) {
+ e.getfield(EMPTY_ARGS_NAME);
+ } else {
+ e.create_arg_array();
+ }
+
+ e.getfield(methodProxyField);
+ e.invoke_interface(METHOD_INTERCEPTOR, INTERCEPT);
+ e.unbox_or_zero(sig.getReturnType());
+ e.return_value();
+
+ e.mark(nullInterceptor);
+ superHelper(e, method);
+ e.return_value();
+ e.end_method();
+ }
+ generateFindProxy(ce, sigMap);
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) throws Exception {
+ /* generates:
+ static {
+ Class thisClass = Class.forName("NameOfThisClass");
+ Class cls = Class.forName("java.lang.Object");
+ String[] sigs = new String[]{ "toString", "()Ljava/lang/String;", ... };
+ Method[] methods = cls.getDeclaredMethods();
+ methods = ReflectUtils.findMethods(sigs, methods);
+ METHOD_0 = methods[0];
+ CGLIB$ACCESS_0 = MethodProxy.create(cls, thisClass, "()Ljava/lang/String;", "toString", "CGLIB$ACCESS_0");
+ ...
+ }
+ */
+
+ e.push(0);
+ e.newarray();
+ e.putfield(EMPTY_ARGS_NAME);
+
+ Local thisclass = e.make_local();
+ Local declaringclass = e.make_local();
+ EmitUtils.load_class_this(e);
+ e.store_local(thisclass);
+
+ Map methodsByClass = CollectionUtils.bucket(methods, METHOD_TO_CLASS);
+ for (Iterator i = methodsByClass.keySet().iterator(); i.hasNext();) {
+ ClassInfo classInfo = (ClassInfo)i.next();
+
+ List classMethods = (List)methodsByClass.get(classInfo);
+ e.push(2 * classMethods.size());
+ e.newarray(Constants.TYPE_STRING);
+ for (int index = 0; index < classMethods.size(); index++) {
+ MethodInfo method = (MethodInfo)classMethods.get(index);
+ Signature sig = method.getSignature();
+ e.dup();
+ e.push(2 * index);
+ e.push(sig.getName());
+ e.aastore();
+ e.dup();
+ e.push(2 * index + 1);
+ e.push(sig.getDescriptor());
+ e.aastore();
+ }
+
+ EmitUtils.load_class(e, classInfo.getType());
+ e.dup();
+ e.store_local(declaringclass);
+ e.invoke_virtual(Constants.TYPE_CLASS, GET_DECLARED_METHODS);
+ e.invoke_static(REFLECT_UTILS, FIND_METHODS);
+
+ for (int index = 0; index < classMethods.size(); index++) {
+ MethodInfo method = (MethodInfo)classMethods.get(index);
+ Signature sig = method.getSignature();
+ Signature impl = context.getImplSignature(method);
+ e.dup();
+ e.push(index);
+ e.array_load(METHOD);
+ e.putfield(getMethodField(impl));
+
+ e.load_local(declaringclass);
+ e.load_local(thisclass);
+ e.push(sig.getDescriptor());
+ e.push(sig.getName());
+ e.push(impl.getName());
+ e.invoke_static(METHOD_PROXY, MAKE_PROXY);
+ e.putfield(getMethodProxyField(impl));
+ }
+ e.pop();
+ }
+ }
+
+ public void generateFindProxy(ClassEmitter ce, final Map sigMap) {
+ final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC | Constants.ACC_STATIC,
+ FIND_PROXY,
+ null);
+ e.load_arg(0);
+ e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
+ ObjectSwitchCallback callback = new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ e.getfield((String)sigMap.get(key));
+ e.return_value();
+ }
+ public void processDefault() {
+ e.aconst_null();
+ e.return_value();
+ }
+ };
+ EmitUtils.string_switch(e,
+ (String[])sigMap.keySet().toArray(new String[0]),
+ Constants.SWITCH_STYLE_HASH,
+ callback);
+ e.end_method();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodProxy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodProxy.java
new file mode 100644
index 0000000..6efb2b5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MethodProxy.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.GeneratorStrategy;
+import org.powermock.api.mockito.repackaged.cglib.core.NamingPolicy;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.reflect.FastClass;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+/**
+ * Classes generated by {@link Enhancer} pass this object to the
+ * registered {@link MethodInterceptor} objects when an intercepted method is invoked. It can
+ * be used to either invoke the original method, or call the same method on a different
+ * object of the same type.
+ * @version $Id: MethodProxy.java,v 1.14 2008/05/26 04:05:50 herbyderby Exp $
+ */
+public class MethodProxy {
+ private final Object initLock = new Object();
+ private Signature sig1;
+ private Signature sig2;
+ private CreateInfo createInfo;
+ private volatile FastClassInfo fastClassInfo;
+
+ private MethodProxy() {
+ }
+
+ /**
+ * For internal use by {@link Enhancer} only; see the {@link org.powermock.api.mockito.repackaged.cglib.reflect.FastMethod} class
+ * for similar functionality.
+ */
+ public static MethodProxy create(Class c1, Class c2, String desc, String name1, String name2) {
+ MethodProxy proxy = new MethodProxy();
+ proxy.sig1 = new Signature(name1, desc);
+ proxy.sig2 = new Signature(name2, desc);
+ proxy.createInfo = new CreateInfo(c1, c2);
+ return proxy;
+ }
+
+ private static FastClass helper(CreateInfo ci, Class type) {
+ FastClass.Generator g = new FastClass.Generator();
+ g.setType(type);
+ g.setClassLoader(ci.c2.getClassLoader());
+ g.setNamingPolicy(ci.namingPolicy);
+ g.setStrategy(ci.strategy);
+ g.setAttemptLoad(ci.attemptLoad);
+ return g.create();
+ }
+
+ /**
+ * Return the <code>MethodProxy</code> used when intercepting the method
+ * matching the given signature.
+ * @param type the class generated by Enhancer
+ * @param sig the signature to match
+ * @return the MethodProxy instance, or null if no applicable matching method is found
+ * @throws IllegalArgumentException if the Class was not created by Enhancer or does not use a MethodInterceptor
+ */
+ public static MethodProxy find(Class type, Signature sig) {
+ try {
+ Method m = type.getDeclaredMethod(MethodInterceptorGenerator.FIND_PROXY_NAME,
+ MethodInterceptorGenerator.FIND_PROXY_TYPES);
+ return (MethodProxy)m.invoke(null, new Object[]{ sig });
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException("Class " + type + " does not use a MethodInterceptor");
+ } catch (IllegalAccessException e) {
+ throw new CodeGenerationException(e);
+ } catch (InvocationTargetException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ private void init()
+ {
+ /*
+ * Using a volatile invariant allows us to initialize the FastClass and
+ * method index pairs atomically.
+ *
+ * Double-checked locking is safe with volatile in Java 5. Before 1.5 this
+ * code could allow fastClassInfo to be instantiated more than once, which
+ * appears to be benign.
+ */
+ if (fastClassInfo == null)
+ {
+ synchronized (initLock)
+ {
+ if (fastClassInfo == null)
+ {
+ CreateInfo ci = createInfo;
+
+ FastClassInfo fci = new FastClassInfo();
+ fci.f1 = helper(ci, ci.c1);
+ fci.f2 = helper(ci, ci.c2);
+ fci.i1 = fci.f1.getIndex(sig1);
+ fci.i2 = fci.f2.getIndex(sig2);
+ fastClassInfo = fci;
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the signature of the proxied method.
+ */
+ public Signature getSignature() {
+ return sig1;
+ }
+
+ /**
+ * Return the name of the synthetic method created by CGLIB which is
+ * used by {@link #invokeSuper} to invoke the superclass
+ * (non-intercepted) method implementation. The parameter types are
+ * the same as the proxied method.
+ */
+ public String getSuperName() {
+ return sig2.getName();
+ }
+
+ /**
+ * Return the {@link org.powermock.api.mockito.repackaged.cglib.reflect.FastClass} method index
+ * for the method used by {@link #invokeSuper}. This index uniquely
+ * identifies the method within the generated proxy, and therefore
+ * can be useful to reference external metadata.
+ * @see #getSuperName
+ */
+ public int getSuperIndex() {
+ init();
+ return fastClassInfo.i2;
+ }
+
+ /**
+ * Invoke the original method, on a different object of the same type.
+ * @param obj the compatible object; recursion will result if you use the object passed as the first
+ * argument to the MethodInterceptor (usually not what you want)
+ * @param args the arguments passed to the intercepted method; you may substitute a different
+ * argument array as long as the types are compatible
+ * @see MethodInterceptor#intercept
+ * @throws Throwable the bare exceptions thrown by the called method are passed through
+ * without wrapping in an <code>InvocationTargetException</code>
+ */
+ public Object invoke(Object obj, Object[] args) throws Throwable {
+ try {
+ init();
+ FastClassInfo fci = fastClassInfo;
+ return fci.f1.invoke(fci.i1, obj, args);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ } catch (IllegalArgumentException e) {
+ if (fastClassInfo.i1 < 0)
+ throw new IllegalArgumentException("Protected method: " + sig1);
+ throw e;
+ }
+ }
+
+ /**
+ * Invoke the original (super) method on the specified object.
+ * @param obj the enhanced object, must be the object passed as the first
+ * argument to the MethodInterceptor
+ * @param args the arguments passed to the intercepted method; you may substitute a different
+ * argument array as long as the types are compatible
+ * @see MethodInterceptor#intercept
+ * @throws Throwable the bare exceptions thrown by the called method are passed through
+ * without wrapping in an <code>InvocationTargetException</code>
+ */
+ public Object invokeSuper(Object obj, Object[] args) throws Throwable {
+ try {
+ init();
+ FastClassInfo fci = fastClassInfo;
+ return fci.f2.invoke(fci.i2, obj, args);
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ }
+
+ private static class FastClassInfo
+ {
+ FastClass f1;
+ FastClass f2;
+ int i1;
+ int i2;
+ }
+
+ private static class CreateInfo
+ {
+ Class c1;
+ Class c2;
+ NamingPolicy namingPolicy;
+ GeneratorStrategy strategy;
+ boolean attemptLoad;
+
+ public CreateInfo(Class c1, Class c2)
+ {
+ this.c1 = c1;
+ this.c2 = c2;
+ AbstractClassGenerator fromEnhancer = AbstractClassGenerator.getCurrent();
+ if (fromEnhancer != null) {
+ namingPolicy = fromEnhancer.getNamingPolicy();
+ strategy = fromEnhancer.getStrategy();
+ attemptLoad = fromEnhancer.getAttemptLoad();
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Mixin.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Mixin.java
new file mode 100644
index 0000000..617feb0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Mixin.java
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassesKey;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+
+/**
+ * <code>Mixin</code> allows
+ * multiple objects to be combined into a single larger object. The
+ * methods in the generated object simply call the original methods in the
+ * underlying "delegate" objects.
+ * @author Chris Nokleberg
+ * @version $Id: Mixin.java,v 1.7 2005/09/27 11:42:27 baliuka Exp $
+ */
+abstract public class Mixin {
+ public static final int STYLE_INTERFACES = 0;
+ public static final int STYLE_BEANS = 1;
+ public static final int STYLE_EVERYTHING = 2;
+ private static final MixinKey KEY_FACTORY =
+ (MixinKey) KeyFactory.create(MixinKey.class, KeyFactory.CLASS_BY_NAME);
+ private static final Map ROUTE_CACHE = Collections.synchronizedMap(new HashMap());
+
+ /**
+ * Helper method to create an interface mixin. For finer control over the
+ * generated instance, use a new instance of <code>Mixin</code>
+ * instead of this static method.
+ * TODO
+ */
+ public static Mixin create(Object[] delegates) {
+ Generator gen = new Generator();
+ gen.setDelegates(delegates);
+ return gen.create();
+ }
+
+ /**
+ * Helper method to create an interface mixin. For finer control over the
+ * generated instance, use a new instance of <code>Mixin</code>
+ * instead of this static method.
+ * TODO
+ */
+ public static Mixin create(Class[] interfaces, Object[] delegates) {
+ Generator gen = new Generator();
+ gen.setClasses(interfaces);
+ gen.setDelegates(delegates);
+ return gen.create();
+ }
+
+ public static Mixin createBean(Object[] beans) {
+
+ return createBean(null, beans);
+
+ }
+
+ /**
+ * Helper method to create a bean mixin. For finer control over the
+ * generated instance, use a new instance of <code>Mixin</code>
+ * instead of this static method.
+ * TODO
+ */
+ public static Mixin createBean(ClassLoader loader,Object[] beans) {
+ Generator gen = new Generator();
+ gen.setStyle(STYLE_BEANS);
+ gen.setDelegates(beans);
+ gen.setClassLoader(loader);
+ return gen.create();
+ }
+
+ public static Class[] getClasses(Object[] delegates) {
+ return (Class[])route(delegates).classes.clone();
+ }
+
+ private static Route route(Object[] delegates) {
+ Object key = ClassesKey.create(delegates);
+ Route route = (Route)ROUTE_CACHE.get(key);
+ if (route == null) {
+ ROUTE_CACHE.put(key, route = new Route(delegates));
+ }
+ return route;
+ }
+
+ abstract public Mixin newInstance(Object[] delegates);
+
+ interface MixinKey {
+ public Object newInstance(int style, String[] classes, int[] route);
+ }
+
+// public static int[] getRoute(Object[] delegates) {
+// return (int[])route(delegates).route.clone();
+// }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(Mixin.class.getName());
+
+ private Class[] classes;
+ private Object[] delegates;
+ private int style = STYLE_INTERFACES;
+
+ private int[] route;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return classes[0].getClassLoader(); // is this right?
+ }
+
+ public void setStyle(int style) {
+ switch (style) {
+ case STYLE_INTERFACES:
+ case STYLE_BEANS:
+ case STYLE_EVERYTHING:
+ this.style = style;
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown mixin style: " + style);
+ }
+ }
+
+ public void setClasses(Class[] classes) {
+ this.classes = classes;
+ }
+
+ public void setDelegates(Object[] delegates) {
+ this.delegates = delegates;
+ }
+
+ public Mixin create() {
+ if (classes == null && delegates == null) {
+ throw new IllegalStateException("Either classes or delegates must be set");
+ }
+ switch (style) {
+ case STYLE_INTERFACES:
+ if (classes == null) {
+ Route r = route(delegates);
+ classes = r.classes;
+ route = r.route;
+ }
+ break;
+ case STYLE_BEANS:
+ // fall-through
+ case STYLE_EVERYTHING:
+ if (classes == null) {
+ classes = ReflectUtils.getClasses(delegates);
+ } else {
+ if (delegates != null) {
+ Class[] temp = ReflectUtils.getClasses(delegates);
+ if (classes.length != temp.length) {
+ throw new IllegalStateException("Specified classes are incompatible with delegates");
+ }
+ for (int i = 0; i < classes.length; i++) {
+ if (!classes[i].isAssignableFrom(temp[i])) {
+ throw new IllegalStateException("Specified class " + classes[i] + " is incompatible with delegate class " + temp[i] + " (index " + i + ")");
+ }
+ }
+ }
+ }
+ }
+ setNamePrefix(classes[ReflectUtils.findPackageProtected(classes)].getName());
+
+ return (Mixin)super.create(KEY_FACTORY.newInstance(style, ReflectUtils.getNames( classes ), route));
+ }
+
+ public void generateClass(ClassVisitor v) {
+ switch (style) {
+ case STYLE_INTERFACES:
+ new MixinEmitter(v, getClassName(), classes, route);
+ break;
+ case STYLE_BEANS:
+ new MixinBeanEmitter(v, getClassName(), classes);
+ break;
+ case STYLE_EVERYTHING:
+ new MixinEverythingEmitter(v, getClassName(), classes);
+ break;
+ }
+ }
+
+ protected Object firstInstance(Class type) {
+ return ((Mixin)ReflectUtils.newInstance(type)).newInstance(delegates);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return ((Mixin)instance).newInstance(delegates);
+ }
+ }
+
+ private static class Route
+ {
+ private Class[] classes;
+ private int[] route;
+
+ Route(Object[] delegates) {
+ Map map = new HashMap();
+ ArrayList collect = new ArrayList();
+ for (int i = 0; i < delegates.length; i++) {
+ Class delegate = delegates[i].getClass();
+ collect.clear();
+ ReflectUtils.addAllInterfaces(delegate, collect);
+ for (Iterator it = collect.iterator(); it.hasNext();) {
+ Class iface = (Class)it.next();
+ if (!map.containsKey(iface)) {
+ map.put(iface, new Integer(i));
+ }
+ }
+ }
+ classes = new Class[map.size()];
+ route = new int[map.size()];
+ int index = 0;
+ for (Iterator it = map.keySet().iterator(); it.hasNext();) {
+ Class key = (Class)it.next();
+ classes[index] = key;
+ route[index] = ((Integer)map.get(key)).intValue();
+ index++;
+ }
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinBeanEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinBeanEmitter.java
new file mode 100644
index 0000000..9dbc77f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinBeanEmitter.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Chris Nokleberg
+ * @version $Id: MixinBeanEmitter.java,v 1.2 2004/06/24 21:15:20 herbyderby Exp $
+ */
+class MixinBeanEmitter extends MixinEmitter {
+ public MixinBeanEmitter(ClassVisitor v, String className, Class[] classes) {
+ super(v, className, classes, null);
+ }
+
+ protected Class[] getInterfaces(Class[] classes) {
+ return null;
+ }
+
+ protected Method[] getMethods(Class type) {
+ return ReflectUtils.getPropertyMethods(ReflectUtils.getBeanProperties(type), true, true);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEmitter.java
new file mode 100644
index 0000000..c73cf3b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEmitter.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodWrapper;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Chris Nokleberg
+ * @version $Id: MixinEmitter.java,v 1.9 2006/08/27 21:04:37 herbyderby Exp $
+ */
+class MixinEmitter extends ClassEmitter {
+ private static final String FIELD_NAME = "CGLIB$DELEGATES";
+ private static final Signature CSTRUCT_OBJECT_ARRAY =
+ TypeUtils.parseConstructor("Object[]");
+ private static final Type MIXIN =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.proxy.Mixin");
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", MIXIN, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
+
+ public MixinEmitter(ClassVisitor v, String className, Class[] classes, int[] route) {
+ super(v);
+
+ begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ className,
+ MIXIN,
+ TypeUtils.getTypes(getInterfaces(classes)),
+ Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(this);
+ EmitUtils.factory_method(this, NEW_INSTANCE);
+
+ declare_field(Constants.ACC_PRIVATE, FIELD_NAME, Constants.TYPE_OBJECT_ARRAY, null);
+
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
+ e.load_this();
+ e.super_invoke_constructor();
+ e.load_this();
+ e.load_arg(0);
+ e.putfield(FIELD_NAME);
+ e.return_value();
+ e.end_method();
+
+ Set unique = new HashSet();
+ for (int i = 0; i < classes.length; i++) {
+ Method[] methods = getMethods(classes[i]);
+ for (int j = 0; j < methods.length; j++) {
+ if (unique.add(MethodWrapper.create(methods[j]))) {
+ MethodInfo method = ReflectUtils.getMethodInfo(methods[j]);
+ e = EmitUtils.begin_method(this, method, Constants.ACC_PUBLIC);
+ e.load_this();
+ e.getfield(FIELD_NAME);
+ e.aaload((route != null) ? route[i] : i);
+ e.checkcast(method.getClassInfo().getType());
+ e.load_args();
+ e.invoke(method);
+ e.return_value();
+ e.end_method();
+ }
+ }
+ }
+
+ end_class();
+ }
+
+ protected Class[] getInterfaces(Class[] classes) {
+ return classes;
+ }
+
+ protected Method[] getMethods(Class type) {
+ return type.getMethods();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEverythingEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEverythingEmitter.java
new file mode 100644
index 0000000..e1a676e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/MixinEverythingEmitter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.CollectionUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.RejectModifierPredicate;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Chris Nokleberg
+ * @version $Id: MixinEverythingEmitter.java,v 1.3 2004/06/24 21:15:19 herbyderby Exp $
+ */
+class MixinEverythingEmitter extends MixinEmitter {
+
+ public MixinEverythingEmitter(ClassVisitor v, String className, Class[] classes) {
+ super(v, className, classes, null);
+ }
+
+ protected Class[] getInterfaces(Class[] classes) {
+ List list = new ArrayList();
+ for (int i = 0; i < classes.length; i++) {
+ ReflectUtils.addAllInterfaces(classes[i], list);
+ }
+ return (Class[])list.toArray(new Class[list.size()]);
+ }
+
+ protected Method[] getMethods(Class type) {
+ List methods = new ArrayList(Arrays.asList(type.getMethods()));
+ CollectionUtils.filter(methods, new RejectModifierPredicate(Modifier.FINAL | Modifier.STATIC));
+ return (Method[])methods.toArray(new Method[methods.size()]);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOp.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOp.java
new file mode 100644
index 0000000..1f4d5ac
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOp.java
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * Methods using this {@link Enhancer} callback will delegate directly to the
+ * default (super) implementation in the base class.
+ */
+public interface NoOp extends Callback
+{
+ /**
+ * A thread-safe singleton instance of the <code>NoOp</code> callback.
+ */
+ public static final NoOp INSTANCE = new NoOp() { };
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOpGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOpGenerator.java
new file mode 100644
index 0000000..c346e5e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/NoOpGenerator.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.Iterator;
+import java.util.List;
+
+class NoOpGenerator
+implements CallbackGenerator
+{
+ public static final NoOpGenerator INSTANCE = new NoOpGenerator();
+
+ public void generate(ClassEmitter ce, Context context, List methods) {
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ MethodInfo method = (MethodInfo)it.next();
+ if (TypeUtils.isProtected(context.getOriginalModifiers(method)) &&
+ TypeUtils.isPublic(method.getModifiers())) {
+ CodeEmitter e = EmitUtils.begin_method(ce, method);
+ e.load_this();
+ e.load_args();
+ e.super_invoke();
+ e.return_value();
+ e.end_method();
+ }
+ }
+ }
+
+ public void generateStatic(CodeEmitter e, Context context, List methods) { }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Proxy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Proxy.java
new file mode 100644
index 0000000..dcca35c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/Proxy.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * This class is meant to be used as replacement for
+ * <code>java.lang.reflect.Proxy</code> under JDK 1.2. There are some known
+ * subtle differences:
+ * <ul>
+ * <li>The exceptions returned by invoking <code>getExceptionTypes</code>
+ * on the <code>Method</code> passed to the <code>invoke</code> method
+ * <b>are</b> the exact set that can be thrown without resulting in an
+ * <code>UndeclaredThrowableException</code> being thrown.
+ * <li>{@link UndeclaredThrowableException} is used instead
+ * of <code>java.lang.reflect.UndeclaredThrowableException</code>.
+ * </ul>
+ * <p>
+ * @version $Id: Proxy.java,v 1.6 2004/06/24 21:15:19 herbyderby Exp $
+ */
+public class Proxy implements Serializable {
+ private static final CallbackFilter BAD_OBJECT_METHOD_FILTER = new CallbackFilter() {
+ public int accept(Method method, List<Method> allMethods) {
+ if (method.getDeclaringClass().getName().equals("java.lang.Object")) {
+ String name = method.getName();
+ if (!(name.equals("hashCode") ||
+ name.equals("equals") ||
+ name.equals("toString"))) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ };
+ protected InvocationHandler h;
+
+ protected Proxy(InvocationHandler h) {
+ Enhancer.registerCallbacks(getClass(), new Callback[]{ h, null });
+ this.h = h;
+ }
+
+ public static InvocationHandler getInvocationHandler(Object proxy) {
+ if (!(proxy instanceof ProxyImpl)) {
+ throw new IllegalArgumentException("Object is not a proxy");
+ }
+ return ((Proxy)proxy).h;
+ }
+
+ public static Class getProxyClass(ClassLoader loader, Class[] interfaces) {
+ Enhancer e = new Enhancer();
+ e.setSuperclass(ProxyImpl.class);
+ e.setInterfaces(interfaces);
+ e.setCallbackTypes(new Class[]{
+ InvocationHandler.class,
+ NoOp.class,
+ });
+ e.setCallbackFilter(BAD_OBJECT_METHOD_FILTER);
+ e.setUseFactory(false);
+ return e.createClass();
+ }
+
+ public static boolean isProxyClass(Class cl) {
+ return cl.getSuperclass().equals(ProxyImpl.class);
+ }
+
+ public static Object newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) {
+ try {
+ Class clazz = getProxyClass(loader, interfaces);
+ return clazz.getConstructor(new Class[]{ InvocationHandler.class }).newInstance(new Object[]{ h });
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ // private for security of isProxyClass
+ private static class ProxyImpl extends Proxy {
+ protected ProxyImpl(InvocationHandler h) {
+ super(h);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/ProxyRefDispatcher.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/ProxyRefDispatcher.java
new file mode 100644
index 0000000..d5c0c60
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/ProxyRefDispatcher.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+/**
+ * Dispatching {@link Enhancer} callback. This is the same as the
+ * {@link Dispatcher} except for the addition of an argument
+ * which references the proxy object.
+ */
+public interface ProxyRefDispatcher extends Callback {
+ /**
+ * Return the object which the original method invocation should
+ * be dispatched. This method is called for <b>every</b> method invocation.
+ * @param proxy a reference to the proxy (generated) object
+ * @return an object that can invoke the method
+ */
+ Object loadObject(Object proxy) throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/UndeclaredThrowableException.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/UndeclaredThrowableException.java
new file mode 100644
index 0000000..084cba7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/proxy/UndeclaredThrowableException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged.cglib.proxy;
+
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+
+/**
+ * Used by {@link Proxy} as a replacement for <code>java.lang.reflect.UndeclaredThrowableException</code>.
+ * @author Juozas Baliuka
+ */
+public class UndeclaredThrowableException extends CodeGenerationException {
+ /**
+ * Creates a new instance of <code>UndeclaredThrowableException</code> without detail message.
+ */
+ public UndeclaredThrowableException(Throwable t) {
+ super(t);
+ }
+
+ public Throwable getUndeclaredThrowable() {
+ return getCause();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/ConstructorDelegate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/ConstructorDelegate.java
new file mode 100644
index 0000000..26a549f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/ConstructorDelegate.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * @author Chris Nokleberg
+ * @version $Id: ConstructorDelegate.java,v 1.20 2006/03/05 02:43:19 herbyderby Exp $
+ */
+abstract public class ConstructorDelegate {
+ private static final ConstructorKey KEY_FACTORY =
+ (ConstructorKey) KeyFactory.create(ConstructorKey.class, KeyFactory.CLASS_BY_NAME);
+
+ protected ConstructorDelegate() {
+ }
+
+ public static ConstructorDelegate create(Class targetClass, Class iface) {
+ Generator gen = new Generator();
+ gen.setTargetClass(targetClass);
+ gen.setInterface(iface);
+ return gen.create();
+ }
+
+ interface ConstructorKey {
+ public Object newInstance(String declaring, String iface);
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(ConstructorDelegate.class.getName());
+ private static final Type CONSTRUCTOR_DELEGATE =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.reflect.ConstructorDelegate");
+
+ private Class iface;
+ private Class targetClass;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ public void setInterface(Class iface) {
+ this.iface = iface;
+ }
+
+ public void setTargetClass(Class targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ public ConstructorDelegate create() {
+ setNamePrefix(targetClass.getName());
+ Object key = KEY_FACTORY.newInstance(iface.getName(), targetClass.getName());
+ return (ConstructorDelegate)super.create(key);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return targetClass.getClassLoader();
+ }
+
+ public void generateClass(ClassVisitor v) {
+ setNamePrefix(targetClass.getName());
+
+ final Method newInstance = ReflectUtils.findNewInstance(iface);
+ if (!newInstance.getReturnType().isAssignableFrom(targetClass)) {
+ throw new IllegalArgumentException("incompatible return type");
+ }
+ final Constructor constructor;
+ try {
+ constructor = targetClass.getDeclaredConstructor(newInstance.getParameterTypes());
+ } catch (NoSuchMethodException e) {
+ throw new IllegalArgumentException("interface does not match any known constructor");
+ }
+
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ CONSTRUCTOR_DELEGATE,
+ new Type[]{ Type.getType(iface) },
+ Constants.SOURCE_FILE);
+ Type declaring = Type.getType(constructor.getDeclaringClass());
+ EmitUtils.null_constructor(ce);
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC,
+ ReflectUtils.getSignature(newInstance),
+ ReflectUtils.getExceptionTypes(newInstance));
+ e.new_instance(declaring);
+ e.dup();
+ e.load_args();
+ e.invoke_constructor(declaring, ReflectUtils.getSignature(constructor));
+ e.return_value();
+ e.end_method();
+ ce.end_class();
+ }
+
+ protected Object firstInstance(Class type) {
+ return ReflectUtils.newInstance(type);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClass.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClass.java
new file mode 100644
index 0000000..f9a4e63
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClass.java
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+abstract public class FastClass
+{
+ private Class type;
+
+ protected FastClass() {
+ throw new Error("Using the FastClass empty constructor--please report to the cglib-devel mailing list");
+ }
+
+ protected FastClass(Class type) {
+ this.type = type;
+ }
+
+ public static FastClass create(Class type) {
+
+ return create(type.getClassLoader(),type);
+
+ }
+ public static FastClass create(ClassLoader loader, Class type) {
+ Generator gen = new Generator();
+ gen.setType(type);
+ gen.setClassLoader(loader);
+ return gen.create();
+ }
+
+ protected static String getSignatureWithoutReturnType(String name, Class[] parameterTypes) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(name);
+ sb.append('(');
+ for (int i = 0; i < parameterTypes.length; i++) {
+ sb.append(Type.getDescriptor(parameterTypes[i]));
+ }
+ sb.append(')');
+ return sb.toString();
+ }
+
+ public Object invoke(String name, Class[] parameterTypes, Object obj, Object[] args) throws InvocationTargetException {
+ return invoke(getIndex(name, parameterTypes), obj, args);
+ }
+
+ public Object newInstance() throws InvocationTargetException {
+ return newInstance(getIndex(Constants.EMPTY_CLASS_ARRAY), null);
+ }
+
+ public Object newInstance(Class[] parameterTypes, Object[] args) throws InvocationTargetException {
+ return newInstance(getIndex(parameterTypes), args);
+ }
+
+ public FastMethod getMethod(Method method) {
+ return new FastMethod(this, method);
+ }
+
+ public FastConstructor getConstructor(Constructor constructor) {
+ return new FastConstructor(this, constructor);
+ }
+
+ public FastMethod getMethod(String name, Class[] parameterTypes) {
+ try {
+ return getMethod(type.getMethod(name, parameterTypes));
+ } catch (NoSuchMethodException e) {
+ throw new NoSuchMethodError(e.getMessage());
+ }
+ }
+
+ public FastConstructor getConstructor(Class[] parameterTypes) {
+ try {
+ return getConstructor(type.getConstructor(parameterTypes));
+ } catch (NoSuchMethodException e) {
+ throw new NoSuchMethodError(e.getMessage());
+ }
+ }
+
+ public String getName() {
+ return type.getName();
+ }
+
+ public Class getJavaClass() {
+ return type;
+ }
+
+ public String toString() {
+ return type.toString();
+ }
+
+ public int hashCode() {
+ return type.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof FastClass)) {
+ return false;
+ }
+ return type.equals(((FastClass)o).type);
+ }
+
+ /**
+ * Return the index of the matching method. The index may be used
+ * later to invoke the method with less overhead. If more than one
+ * method matches (i.e. they differ by return type only), one is
+ * chosen arbitrarily.
+ * @see #invoke(int, Object, Object[])
+ * @param name the method name
+ * @param parameterTypes the parameter array
+ * @return the index, or <code>-1</code> if none is found.
+ */
+ abstract public int getIndex(String name, Class[] parameterTypes);
+
+ /**
+ * Return the index of the matching constructor. The index may be used
+ * later to create a new instance with less overhead.
+ * @see #newInstance(int, Object[])
+ * @param parameterTypes the parameter array
+ * @return the constructor index, or <code>-1</code> if none is found.
+ */
+ abstract public int getIndex(Class[] parameterTypes);
+
+ /**
+ * Invoke the method with the specified index.
+ * @see getIndex(name, Class[])
+ * @param index the method index
+ * @param obj the object the underlying method is invoked from
+ * @param args the arguments used for the method call
+ * @throws InvocationTargetException if the underlying method throws an exception
+ */
+ abstract public Object invoke(int index, Object obj, Object[] args) throws InvocationTargetException;
+
+ /**
+ * Create a new instance using the specified constructor index and arguments.
+ * @see getIndex(Class[])
+ * @param index the constructor index
+ * @param args the arguments passed to the constructor
+ * @throws InvocationTargetException if the constructor throws an exception
+ */
+ abstract public Object newInstance(int index, Object[] args) throws InvocationTargetException;
+
+ abstract public int getIndex(Signature sig);
+
+ /**
+ * Returns the maximum method index for this class.
+ */
+ abstract public int getMaxIndex();
+
+ public static class Generator extends AbstractClassGenerator
+ {
+ private static final Source SOURCE = new Source(FastClass.class.getName());
+ private Class type;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ public void setType(Class type) {
+ this.type = type;
+ }
+
+ public FastClass create() {
+ setNamePrefix(type.getName());
+ return (FastClass)super.create(type.getName());
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return type.getClassLoader();
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ new FastClassEmitter(v, getClassName(), type);
+ }
+
+ protected Object firstInstance(Class type) {
+ return ReflectUtils.newInstance(type,
+ new Class[]{ Class.class },
+ new Object[]{ this.type });
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClassEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClassEmitter.java
new file mode 100644
index 0000000..0813525
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastClassEmitter.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.Block;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CollectionUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.DuplicatesPredicate;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfoTransformer;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ProcessSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.Transformer;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.VisibilityPredicate;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+class FastClassEmitter extends ClassEmitter {
+ private static final Signature CSTRUCT_CLASS =
+ TypeUtils.parseConstructor("Class");
+ private static final Signature METHOD_GET_INDEX =
+ TypeUtils.parseSignature("int getIndex(String, Class[])");
+ private static final Signature SIGNATURE_GET_INDEX =
+ new Signature("getIndex", Type.INT_TYPE, new Type[]{ Constants.TYPE_SIGNATURE });
+ private static final Signature TO_STRING =
+ TypeUtils.parseSignature("String toString()");
+ private static final Signature CONSTRUCTOR_GET_INDEX =
+ TypeUtils.parseSignature("int getIndex(Class[])");
+ private static final Signature INVOKE =
+ TypeUtils.parseSignature("Object invoke(int, Object, Object[])");
+ private static final Signature NEW_INSTANCE =
+ TypeUtils.parseSignature("Object newInstance(int, Object[])");
+ private static final Signature GET_MAX_INDEX =
+ TypeUtils.parseSignature("int getMaxIndex()");
+ private static final Signature GET_SIGNATURE_WITHOUT_RETURN_TYPE =
+ TypeUtils.parseSignature("String getSignatureWithoutReturnType(String, Class[])");
+ private static final Type FAST_CLASS =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.reflect.FastClass");
+ private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
+ TypeUtils.parseType("IllegalArgumentException");
+ private static final Type INVOCATION_TARGET_EXCEPTION =
+ TypeUtils.parseType("java.lang.reflect.InvocationTargetException");
+ private static final Type[] INVOCATION_TARGET_EXCEPTION_ARRAY = { INVOCATION_TARGET_EXCEPTION };
+ private static final int TOO_MANY_METHODS = 100; // TODO
+
+ public FastClassEmitter(ClassVisitor v, String className, Class type) {
+ super(v);
+
+ Type base = Type.getType(type);
+ begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, FAST_CLASS, null, Constants.SOURCE_FILE);
+
+ // constructor
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_CLASS, null);
+ e.load_this();
+ e.load_args();
+ e.super_invoke_constructor(CSTRUCT_CLASS);
+ e.return_value();
+ e.end_method();
+
+ VisibilityPredicate vp = new VisibilityPredicate(type, false);
+ List methods = ReflectUtils.addAllMethods(type, new ArrayList());
+ CollectionUtils.filter(methods, vp);
+ CollectionUtils.filter(methods, new DuplicatesPredicate());
+ List constructors = new ArrayList(Arrays.asList(type.getDeclaredConstructors()));
+ CollectionUtils.filter(constructors, vp);
+
+ // getIndex(String)
+ emitIndexBySignature(methods);
+
+ // getIndex(String, Class[])
+ emitIndexByClassArray(methods);
+
+ // getIndex(Class[])
+ e = begin_method(Constants.ACC_PUBLIC, CONSTRUCTOR_GET_INDEX, null);
+ e.load_args();
+ List info = CollectionUtils.transform(constructors, MethodInfoTransformer.getInstance());
+ EmitUtils.constructor_switch(e, info, new GetIndexCallback(e, info));
+ e.end_method();
+
+ // invoke(int, Object, Object[])
+ e = begin_method(Constants.ACC_PUBLIC, INVOKE, INVOCATION_TARGET_EXCEPTION_ARRAY);
+ e.load_arg(1);
+ e.checkcast(base);
+ e.load_arg(0);
+ invokeSwitchHelper(e, methods, 2, base);
+ e.end_method();
+
+ // newInstance(int, Object[])
+ e = begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, INVOCATION_TARGET_EXCEPTION_ARRAY);
+ e.new_instance(base);
+ e.dup();
+ e.load_arg(0);
+ invokeSwitchHelper(e, constructors, 1, base);
+ e.end_method();
+
+ // getMaxIndex()
+ e = begin_method(Constants.ACC_PUBLIC, GET_MAX_INDEX, null);
+ e.push(methods.size() - 1);
+ e.return_value();
+ e.end_method();
+
+ end_class();
+ }
+
+ private static void invokeSwitchHelper(final CodeEmitter e, List members, final int arg, final Type base) {
+ final List info = CollectionUtils.transform(members, MethodInfoTransformer.getInstance());
+ final Label illegalArg = e.make_label();
+ Block block = e.begin_block();
+ e.process_switch(getIntRange(info.size()), new ProcessSwitchCallback() {
+ public void processCase(int key, Label end) {
+ MethodInfo method = (MethodInfo)info.get(key);
+ Type[] types = method.getSignature().getArgumentTypes();
+ for (int i = 0; i < types.length; i++) {
+ e.load_arg(arg);
+ e.aaload(i);
+ e.unbox(types[i]);
+ }
+ // TODO: change method lookup process so MethodInfo will already reference base
+ // instead of superclass when superclass method is inaccessible
+ e.invoke(method, base);
+ if (!TypeUtils.isConstructor(method)) {
+ e.box(method.getSignature().getReturnType());
+ }
+ e.return_value();
+ }
+ public void processDefault() {
+ e.goTo(illegalArg);
+ }
+ });
+ block.end();
+ EmitUtils.wrap_throwable(block, INVOCATION_TARGET_EXCEPTION);
+ e.mark(illegalArg);
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Cannot find matching method/constructor");
+ }
+
+ private static int[] getIntRange(int length) {
+ int[] range = new int[length];
+ for (int i = 0; i < length; i++) {
+ range[i] = i;
+ }
+ return range;
+ }
+
+ // TODO: support constructor indices ("<init>")
+ private void emitIndexBySignature(List methods) {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SIGNATURE_GET_INDEX, null);
+ List signatures = CollectionUtils.transform(methods, new Transformer() {
+ public Object transform(Object obj) {
+ return ReflectUtils.getSignature((Method)obj).toString();
+ }
+ });
+ e.load_arg(0);
+ e.invoke_virtual(Constants.TYPE_OBJECT, TO_STRING);
+ signatureSwitchHelper(e, signatures);
+ e.end_method();
+ }
+
+ private void emitIndexByClassArray(List methods) {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, METHOD_GET_INDEX, null);
+ if (methods.size() > TOO_MANY_METHODS) {
+ // hack for big classes
+ List signatures = CollectionUtils.transform(methods, new Transformer() {
+ public Object transform(Object obj) {
+ String s = ReflectUtils.getSignature((Method)obj).toString();
+ return s.substring(0, s.lastIndexOf(')') + 1);
+ }
+ });
+ e.load_args();
+ e.invoke_static(FAST_CLASS, GET_SIGNATURE_WITHOUT_RETURN_TYPE);
+ signatureSwitchHelper(e, signatures);
+ } else {
+ e.load_args();
+ List info = CollectionUtils.transform(methods, MethodInfoTransformer.getInstance());
+ EmitUtils.method_switch(e, info, new GetIndexCallback(e, info));
+ }
+ e.end_method();
+ }
+
+ private void signatureSwitchHelper(final CodeEmitter e, final List signatures) {
+ ObjectSwitchCallback callback = new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ // TODO: remove linear indexOf
+ e.push(signatures.indexOf(key));
+ e.return_value();
+ }
+ public void processDefault() {
+ e.push(-1);
+ e.return_value();
+ }
+ };
+ EmitUtils.string_switch(e,
+ (String[])signatures.toArray(new String[signatures.size()]),
+ Constants.SWITCH_STYLE_HASH,
+ callback);
+ }
+
+ private static class GetIndexCallback implements ObjectSwitchCallback {
+ private CodeEmitter e;
+ private Map indexes = new HashMap();
+
+ public GetIndexCallback(CodeEmitter e, List methods) {
+ this.e = e;
+ int index = 0;
+ for (Iterator it = methods.iterator(); it.hasNext();) {
+ indexes.put(it.next(), new Integer(index++));
+ }
+ }
+
+ public void processCase(Object key, Label end) {
+ e.push(((Integer)indexes.get(key)).intValue());
+ e.return_value();
+ }
+
+ public void processDefault() {
+ e.push(-1);
+ e.return_value();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastConstructor.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastConstructor.java
new file mode 100644
index 0000000..680d3f3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastConstructor.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+public class FastConstructor extends FastMember
+{
+ FastConstructor(FastClass fc, Constructor constructor) {
+ super(fc, constructor, fc.getIndex(constructor.getParameterTypes()));
+ }
+
+ public Class[] getParameterTypes() {
+ return ((Constructor)member).getParameterTypes();
+ }
+
+ public Class[] getExceptionTypes() {
+ return ((Constructor)member).getExceptionTypes();
+ }
+
+ public Object newInstance() throws InvocationTargetException {
+ return fc.newInstance(index, null);
+ }
+
+ public Object newInstance(Object[] args) throws InvocationTargetException {
+ return fc.newInstance(index, args);
+ }
+
+ public Constructor getJavaConstructor() {
+ return (Constructor)member;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMember.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMember.java
new file mode 100644
index 0000000..ca60665
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMember.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import java.lang.reflect.Member;
+
+abstract public class FastMember
+{
+ protected FastClass fc;
+ protected Member member;
+ protected int index;
+
+ protected FastMember(FastClass fc, Member member, int index) {
+ this.fc = fc;
+ this.member = member;
+ this.index = index;
+ }
+
+ abstract public Class[] getParameterTypes();
+ abstract public Class[] getExceptionTypes();
+
+ public int getIndex() {
+ return index;
+ }
+
+ public String getName() {
+ return member.getName();
+ }
+
+ public Class getDeclaringClass() {
+ return fc.getJavaClass();
+ }
+
+ public int getModifiers() {
+ return member.getModifiers();
+ }
+
+ public String toString() {
+ return member.toString();
+ }
+
+ public int hashCode() {
+ return member.hashCode();
+ }
+
+ public boolean equals(Object o) {
+ if (o == null || !(o instanceof FastMember)) {
+ return false;
+ }
+ return member.equals(((FastMember)o).member);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMethod.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMethod.java
new file mode 100644
index 0000000..9275e04
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/FastMethod.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class FastMethod extends FastMember
+{
+ FastMethod(FastClass fc, Method method) {
+ super(fc, method, helper(fc, method));
+ }
+
+ private static int helper(FastClass fc, Method method) {
+ int index = fc.getIndex(method.getName(), method.getParameterTypes());
+ if (index < 0) {
+ Class[] types = method.getParameterTypes();
+ System.err.println("hash=" + method.getName().hashCode() + " size=" + types.length);
+ for (int i = 0; i < types.length; i++) {
+ System.err.println(" types[" + i + "]=" + types[i].getName());
+ }
+ throw new IllegalArgumentException("Cannot find method " + method);
+ }
+ return index;
+ }
+
+ public Class getReturnType() {
+ return ((Method)member).getReturnType();
+ }
+
+ public Class[] getParameterTypes() {
+ return ((Method)member).getParameterTypes();
+ }
+
+ public Class[] getExceptionTypes() {
+ return ((Method)member).getExceptionTypes();
+ }
+
+ public Object invoke(Object obj, Object[] args) throws InvocationTargetException {
+ return fc.invoke(index, obj, args);
+ }
+
+ public Method getJavaMethod() {
+ return (Method)member;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MethodDelegate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MethodDelegate.java
new file mode 100644
index 0000000..f00c499
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MethodDelegate.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.lang.reflect.Method;
+
+// TODO: don't require exact match for return type
+
+/**
+ * <b>DOCUMENTATION FROM APACHE AVALON DELEGATE CLASS</b>
+ *
+ * <p>
+ * Delegates are a typesafe pointer to another method. Since Java does not
+ * have language support for such a construct, this utility will construct
+ * a proxy that forwards method calls to any method with the same signature.
+ * This utility is inspired in part by the C# delegate mechanism. We
+ * implemented it in a Java-centric manner.
+ * </p>
+ *
+ * <h2>Delegate</h2>
+ * <p>
+ * Any interface with one method can become the interface for a delegate.
+ * Consider the example below:
+ * </p>
+ *
+ * <pre>
+ * public interface MainDelegate {
+ * int main(String[] args);
+ * }
+ * </pre>
+ *
+ * <p>
+ * The interface above is an example of an interface that can become a
+ * delegate. It has only one method, and the interface is public. In
+ * order to create a delegate for that method, all we have to do is
+ * call <code>MethodDelegate.create(this, "alternateMain", MainDelegate.class)</code>.
+ * The following program will show how to use it:
+ * </p>
+ *
+ * <pre>
+ * public class Main {
+ * public static int main( String[] args ) {
+ * Main newMain = new Main();
+ * MainDelegate start = (MainDelegate)
+ * MethodDelegate.create(newMain, "alternateMain", MainDelegate.class);
+ * return start.main( args );
+ * }
+ *
+ * public int alternateMain( String[] args ) {
+ * for (int i = 0; i < args.length; i++) {
+ * System.out.println( args[i] );
+ * }
+ * return args.length;
+ * }
+ * }
+ * </pre>
+ *
+ * <p>
+ * By themselves, delegates don't do much. Their true power lies in the fact that
+ * they can be treated like objects, and passed to other methods. In fact that is
+ * one of the key building blocks of building Intelligent Agents which in tern are
+ * the foundation of artificial intelligence. In the above program, we could have
+ * easily created the delegate to match the static <code>main</code> method by
+ * substituting the delegate creation call with this:
+ * <code>MethodDelegate.createStatic(getClass(), "main", MainDelegate.class)</code>.
+ * </p>
+ * <p>
+ * Another key use for Delegates is to register event listeners. It is much easier
+ * to have all the code for your events separated out into methods instead of individual
+ * classes. One of the ways Java gets around that is to create anonymous classes.
+ * They are particularly troublesome because many Debuggers do not know what to do
+ * with them. Anonymous classes tend to duplicate alot of code as well. We can
+ * use any interface with one declared method to forward events to any method that
+ * matches the signature (although the method name can be different).
+ * </p>
+ *
+ * <h3>Equality</h3>
+ * The criteria that we use to test if two delegates are equal are:
+ * <ul>
+ * <li>
+ * They both refer to the same instance. That is, the <code>instance</code>
+ * parameter passed to the newDelegate method was the same for both. The
+ * instances are compared with the identity equality operator, <code>==</code>.
+ * </li>
+ * <li>They refer to the same method as resolved by <code>Method.equals</code>.</li>
+ * </ul>
+ *
+ * @version $Id: MethodDelegate.java,v 1.25 2006/03/05 02:43:19 herbyderby Exp $
+ */
+abstract public class MethodDelegate {
+ private static final MethodDelegateKey KEY_FACTORY =
+ (MethodDelegateKey) KeyFactory.create(MethodDelegateKey.class, KeyFactory.CLASS_BY_NAME);
+
+ protected Object target;
+ protected String eqMethod;
+
+ public static MethodDelegate createStatic(Class targetClass, String methodName, Class iface) {
+ Generator gen = new Generator();
+ gen.setTargetClass(targetClass);
+ gen.setMethodName(methodName);
+ gen.setInterface(iface);
+ return gen.create();
+ }
+
+ public static MethodDelegate create(Object target, String methodName, Class iface) {
+ Generator gen = new Generator();
+ gen.setTarget(target);
+ gen.setMethodName(methodName);
+ gen.setInterface(iface);
+ return gen.create();
+ }
+
+ public boolean equals(Object obj) {
+ MethodDelegate other = (MethodDelegate)obj;
+ return target == other.target && eqMethod.equals(other.eqMethod);
+ }
+
+ public int hashCode() {
+ return target.hashCode() ^ eqMethod.hashCode();
+ }
+
+ public Object getTarget() {
+ return target;
+ }
+
+ abstract public MethodDelegate newInstance(Object target);
+
+ interface MethodDelegateKey {
+ Object newInstance(Class delegateClass, String methodName, Class iface);
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(MethodDelegate.class.getName());
+ private static final Type METHOD_DELEGATE =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.reflect.MethodDelegate");
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", METHOD_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
+
+ private Object target;
+ private Class targetClass;
+ private String methodName;
+ private Class iface;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ public void setTarget(Object target) {
+ this.target = target;
+ this.targetClass = target.getClass();
+ }
+
+ public void setTargetClass(Class targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ public void setMethodName(String methodName) {
+ this.methodName = methodName;
+ }
+
+ public void setInterface(Class iface) {
+ this.iface = iface;
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return targetClass.getClassLoader();
+ }
+
+ public MethodDelegate create() {
+ setNamePrefix(targetClass.getName());
+ Object key = KEY_FACTORY.newInstance(targetClass, methodName, iface);
+ return (MethodDelegate)super.create(key);
+ }
+
+ protected Object firstInstance(Class type) {
+ return ((MethodDelegate) ReflectUtils.newInstance(type)).newInstance(target);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return ((MethodDelegate)instance).newInstance(target);
+ }
+
+ public void generateClass(ClassVisitor v) throws NoSuchMethodException {
+ Method proxy = ReflectUtils.findInterfaceMethod(iface);
+ final Method method = targetClass.getMethod(methodName, proxy.getParameterTypes());
+ if (!proxy.getReturnType().isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException("incompatible return types");
+ }
+
+ MethodInfo methodInfo = ReflectUtils.getMethodInfo(method);
+
+ boolean isStatic = TypeUtils.isStatic(methodInfo.getModifiers());
+ if ((target == null) ^ isStatic) {
+ throw new IllegalArgumentException("Static method " + (isStatic ? "not " : "") + "expected");
+ }
+
+ ClassEmitter ce = new ClassEmitter(v);
+ CodeEmitter e;
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ METHOD_DELEGATE,
+ new Type[]{ Type.getType(iface) },
+ Constants.SOURCE_FILE);
+ ce.declare_field(Constants.PRIVATE_FINAL_STATIC, "eqMethod", Constants.TYPE_STRING, null);
+ EmitUtils.null_constructor(ce);
+
+ // generate proxied method
+ MethodInfo proxied = ReflectUtils.getMethodInfo(iface.getDeclaredMethods()[0]);
+ e = EmitUtils.begin_method(ce, proxied, Constants.ACC_PUBLIC);
+ e.load_this();
+ e.super_getfield("target", Constants.TYPE_OBJECT);
+ e.checkcast(methodInfo.getClassInfo().getType());
+ e.load_args();
+ e.invoke(methodInfo);
+ e.return_value();
+ e.end_method();
+
+ // newInstance
+ e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
+ e.new_instance_this();
+ e.dup();
+ e.dup2();
+ e.invoke_constructor_this();
+ e.getfield("eqMethod");
+ e.super_putfield("eqMethod", Constants.TYPE_STRING);
+ e.load_arg(0);
+ e.super_putfield("target", Constants.TYPE_OBJECT);
+ e.return_value();
+ e.end_method();
+
+ // static initializer
+ e = ce.begin_static();
+ e.push(methodInfo.getSignature().toString());
+ e.putfield("eqMethod");
+ e.return_value();
+ e.end_method();
+
+ ce.end_class();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MulticastDelegate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MulticastDelegate.java
new file mode 100644
index 0000000..836c5a5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/reflect/MulticastDelegate.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.reflect;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ProcessArrayCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+abstract public class MulticastDelegate implements Cloneable {
+ protected Object[] targets = {};
+
+ protected MulticastDelegate() {
+ }
+
+ public static MulticastDelegate create(Class iface) {
+ Generator gen = new Generator();
+ gen.setInterface(iface);
+ return gen.create();
+ }
+
+ public List getTargets() {
+ return new ArrayList(Arrays.asList(targets));
+ }
+
+ abstract public MulticastDelegate add(Object target);
+
+ protected MulticastDelegate addHelper(Object target) {
+ MulticastDelegate copy = newInstance();
+ copy.targets = new Object[targets.length + 1];
+ System.arraycopy(targets, 0, copy.targets, 0, targets.length);
+ copy.targets[targets.length] = target;
+ return copy;
+ }
+
+ public MulticastDelegate remove(Object target) {
+ for (int i = targets.length - 1; i >= 0; i--) {
+ if (targets[i].equals(target)) {
+ MulticastDelegate copy = newInstance();
+ copy.targets = new Object[targets.length - 1];
+ System.arraycopy(targets, 0, copy.targets, 0, i);
+ System.arraycopy(targets, i + 1, copy.targets, i, targets.length - i - 1);
+ return copy;
+ }
+ }
+ return this;
+ }
+
+ abstract public MulticastDelegate newInstance();
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(MulticastDelegate.class.getName());
+ private static final Type MULTICAST_DELEGATE =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.reflect.MulticastDelegate");
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", MULTICAST_DELEGATE, new Type[0]);
+ private static final Signature ADD_DELEGATE =
+ new Signature("add", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
+ private static final Signature ADD_HELPER =
+ new Signature("addHelper", MULTICAST_DELEGATE, new Type[]{ Constants.TYPE_OBJECT });
+
+ private Class iface;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return iface.getClassLoader();
+ }
+
+ public void setInterface(Class iface) {
+ this.iface = iface;
+ }
+
+ public MulticastDelegate create() {
+ setNamePrefix(MulticastDelegate.class.getName());
+ return (MulticastDelegate)super.create(iface.getName());
+ }
+
+ public void generateClass(ClassVisitor cv) {
+ final MethodInfo method = ReflectUtils.getMethodInfo(ReflectUtils.findInterfaceMethod(iface));
+
+ ClassEmitter ce = new ClassEmitter(cv);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ MULTICAST_DELEGATE,
+ new Type[]{ Type.getType(iface) },
+ Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(ce);
+
+ // generate proxied method
+ emitProxy(ce, method);
+
+ // newInstance
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, NEW_INSTANCE, null);
+ e.new_instance_this();
+ e.dup();
+ e.invoke_constructor_this();
+ e.return_value();
+ e.end_method();
+
+ // add
+ e = ce.begin_method(Constants.ACC_PUBLIC, ADD_DELEGATE, null);
+ e.load_this();
+ e.load_arg(0);
+ e.checkcast(Type.getType(iface));
+ e.invoke_virtual_this(ADD_HELPER);
+ e.return_value();
+ e.end_method();
+
+ ce.end_class();
+ }
+
+ private void emitProxy(ClassEmitter ce, final MethodInfo method) {
+ final CodeEmitter e = EmitUtils.begin_method(ce, method, Constants.ACC_PUBLIC);
+ Type returnType = method.getSignature().getReturnType();
+ final boolean returns = returnType != Type.VOID_TYPE;
+ Local result = null;
+ if (returns) {
+ result = e.make_local(returnType);
+ e.zero_or_null(returnType);
+ e.store_local(result);
+ }
+ e.load_this();
+ e.super_getfield("targets", Constants.TYPE_OBJECT_ARRAY);
+ final Local result2 = result;
+ EmitUtils.process_array(e, Constants.TYPE_OBJECT_ARRAY, new ProcessArrayCallback() {
+ public void processElement(Type type) {
+ e.checkcast(Type.getType(iface));
+ e.load_args();
+ e.invoke(method);
+ if (returns) {
+ e.store_local(result2);
+ }
+ }
+ });
+ if (returns) {
+ e.load_local(result);
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ protected Object firstInstance(Class type) {
+ // make a new instance in case first object is used with a long list of targets
+ return ((MulticastDelegate)ReflectUtils.newInstance(type)).newInstance();
+ }
+
+ protected Object nextInstance(Object instance) {
+ return ((MulticastDelegate)instance).newInstance();
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassFilterTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassFilterTransformer.java
new file mode 100644
index 0000000..30f2060
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassFilterTransformer.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+abstract public class AbstractClassFilterTransformer extends AbstractClassTransformer {
+ private ClassTransformer pass;
+ private ClassVisitor target;
+
+ protected AbstractClassFilterTransformer(ClassTransformer pass) {
+ this.pass = pass;
+ }
+
+ public void setTarget(ClassVisitor target) {
+ super.setTarget(target);
+ pass.setTarget(target);
+ }
+
+ abstract protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces);
+
+ public void visit(int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ target = accept(version, access, name, signature, superName, interfaces) ? pass : cv;
+ target.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ public void visitSource(String source, String debug) {
+ target.visitSource(source, debug);
+ }
+
+ public void visitOuterClass(String owner, String name, String desc) {
+ target.visitOuterClass(owner, name, desc);
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return target.visitAnnotation(desc, visible);
+ }
+
+ public void visitAttribute(Attribute attr) {
+ target.visitAttribute(attr);
+ }
+
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ target.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ public FieldVisitor visitField(int access,
+ String name,
+ String desc,
+ String signature,
+ Object value) {
+ return target.visitField(access, name, desc, signature, value);
+ }
+
+ public MethodVisitor visitMethod(int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ return target.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ public void visitEnd() {
+ target.visitEnd();
+ target = null; // just to be safe
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassLoader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassLoader.java
new file mode 100644
index 0000000..391078e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassLoader.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassWriter;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.DebuggingClassWriter;
+
+import java.io.IOException;
+
+abstract public class AbstractClassLoader extends ClassLoader {
+ private static java.security.ProtectionDomain DOMAIN ;
+
+ static{
+
+ DOMAIN = (java.security.ProtectionDomain)
+ java.security.AccessController.doPrivileged(
+ new java.security.PrivilegedAction() {
+ public Object run() {
+ return AbstractClassLoader.class.getProtectionDomain();
+ }
+ });
+ }
+
+ private ClassFilter filter;
+ private ClassLoader classPath;
+
+ protected AbstractClassLoader(ClassLoader parent, ClassLoader classPath, ClassFilter filter) {
+ super(parent);
+ this.filter = filter;
+ this.classPath = classPath;
+ }
+
+ public Class loadClass(String name) throws ClassNotFoundException {
+
+ Class loaded = findLoadedClass(name);
+
+ if( loaded != null ){
+ if( loaded.getClassLoader() == this ){
+ return loaded;
+ }//else reload with this class loader
+ }
+
+ if (!filter.accept(name)) {
+ return super.loadClass(name);
+ }
+ ClassReader r;
+ try {
+
+ java.io.InputStream is = classPath.getResourceAsStream(
+ name.replace('.','/') + ".class"
+ );
+
+ if (is == null) {
+
+ throw new ClassNotFoundException(name);
+
+ }
+ try {
+
+ r = new ClassReader(is);
+
+ } finally {
+
+ is.close();
+
+ }
+ } catch (IOException e) {
+ throw new ClassNotFoundException(name + ":" + e.getMessage());
+ }
+
+ try {
+ ClassWriter w = new DebuggingClassWriter(ClassWriter.COMPUTE_MAXS);
+ getGenerator(r).generateClass(w);
+ byte[] b = w.toByteArray();
+ Class c = super.defineClass(name, b, 0, b.length, DOMAIN);
+ postProcess(c);
+ return c;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Error e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ protected ClassGenerator getGenerator(ClassReader r) {
+ return new ClassReaderGenerator(r, attributes(), getFlags());
+ }
+
+ protected int getFlags() {
+ return 0;
+ }
+
+ protected Attribute[] attributes() {
+ return null;
+ }
+
+ protected void postProcess(Class c) {
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassTransformer.java
new file mode 100644
index 0000000..4c4b80a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AbstractClassTransformer.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassAdapter;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+
+abstract public class AbstractClassTransformer extends ClassAdapter implements ClassTransformer {
+ protected AbstractClassTransformer() {
+ super(null);
+ }
+
+ public void setTarget(ClassVisitor target) {
+ cv = target;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AnnotationVisitorTee.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AnnotationVisitorTee.java
new file mode 100644
index 0000000..2644ce9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/AnnotationVisitorTee.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+
+public class AnnotationVisitorTee implements AnnotationVisitor {
+ private AnnotationVisitor av1, av2;
+
+ public AnnotationVisitorTee(AnnotationVisitor av1, AnnotationVisitor av2) {
+ this.av1 = av1;
+ this.av2 = av2;
+ }
+
+ public static AnnotationVisitor getInstance(AnnotationVisitor av1, AnnotationVisitor av2) {
+ if (av1 == null)
+ return av2;
+ if (av2 == null)
+ return av1;
+ return new AnnotationVisitorTee(av1, av2);
+ }
+
+ public void visit(String name, Object value) {
+ av2.visit(name, value);
+ av2.visit(name, value);
+ }
+
+ public void visitEnum(String name, String desc, String value) {
+ av1.visitEnum(name, desc, value);
+ av2.visitEnum(name, desc, value);
+ }
+
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ return getInstance(av1.visitAnnotation(name, desc),
+ av2.visitAnnotation(name, desc));
+ }
+
+ public AnnotationVisitor visitArray(String name) {
+ return getInstance(av1.visitArray(name), av2.visitArray(name));
+ }
+
+ public void visitEnd() {
+ av1.visitEnd();
+ av2.visitEnd();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassEmitterTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassEmitterTransformer.java
new file mode 100644
index 0000000..fec8e6e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassEmitterTransformer.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+
+abstract public class ClassEmitterTransformer extends ClassEmitter implements ClassTransformer {
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilter.java
new file mode 100644
index 0000000..263be21
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilter.java
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+/**
+ *
+ * @author baliuka
+ */
+public interface ClassFilter {
+
+ boolean accept(String className);
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilterTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilterTransformer.java
new file mode 100644
index 0000000..260a0a3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassFilterTransformer.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+public class ClassFilterTransformer extends AbstractClassFilterTransformer {
+ private ClassFilter filter;
+
+ public ClassFilterTransformer(ClassFilter filter, ClassTransformer pass) {
+ super(pass);
+ this.filter = filter;
+ }
+
+ protected boolean accept(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ return filter.accept(name.replace('/', '.'));
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassReaderGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassReaderGenerator.java
new file mode 100644
index 0000000..701fbad
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassReaderGenerator.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassGenerator;
+
+public class ClassReaderGenerator implements ClassGenerator {
+ private final ClassReader r;
+ private final Attribute[] attrs;
+ private final int flags;
+
+ public ClassReaderGenerator(ClassReader r, int flags) {
+ this(r, null, flags);
+ }
+
+ public ClassReaderGenerator(ClassReader r, Attribute[] attrs, int flags) {
+ this.r = r;
+ this.attrs = (attrs != null) ? attrs : new Attribute[0];
+ this.flags = flags;
+ }
+
+ public void generateClass(ClassVisitor v) {
+ r.accept(v, attrs, flags);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformer.java
new file mode 100644
index 0000000..4857a3e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformer.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+
+public interface ClassTransformer extends ClassVisitor {
+ public void setTarget(ClassVisitor target);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerChain.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerChain.java
new file mode 100644
index 0000000..3bac0b3
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerChain.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+public class ClassTransformerChain extends AbstractClassTransformer {
+ private ClassTransformer[] chain;
+
+ public ClassTransformerChain(ClassTransformer[] chain) {
+ this.chain = (ClassTransformer[])chain.clone();
+ }
+
+ public void setTarget(ClassVisitor v) {
+ super.setTarget(chain[0]);
+ ClassVisitor next = v;
+ for (int i = chain.length - 1; i >= 0; i--) {
+ chain[i].setTarget(next);
+ next = chain[i];
+ }
+ }
+
+ public MethodVisitor visitMethod(int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ return cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ sb.append("ClassTransformerChain{");
+ for (int i = 0; i < chain.length; i++) {
+ if (i > 0) {
+ sb.append(", ");
+ }
+ sb.append(chain[i].toString());
+ }
+ sb.append("}");
+ return sb.toString();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerFactory.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerFactory.java
new file mode 100644
index 0000000..6801e54
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerFactory.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+public interface ClassTransformerFactory {
+ ClassTransformer newInstance();
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerTee.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerTee.java
new file mode 100644
index 0000000..df8a1ed
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassTransformerTee.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassAdapter;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+
+public class ClassTransformerTee extends ClassAdapter implements ClassTransformer {
+ private ClassVisitor branch;
+
+ public ClassTransformerTee(ClassVisitor branch) {
+ super(null);
+ this.branch = branch;
+ }
+
+ public void setTarget(ClassVisitor target) {
+ cv = new ClassVisitorTee(branch, target);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassVisitorTee.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassVisitorTee.java
new file mode 100644
index 0000000..66d5171
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/ClassVisitorTee.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+public class ClassVisitorTee implements ClassVisitor {
+ private ClassVisitor cv1, cv2;
+
+ public ClassVisitorTee(ClassVisitor cv1, ClassVisitor cv2) {
+ this.cv1 = cv1;
+ this.cv2 = cv2;
+ }
+
+ public void visit(int version,
+ int access,
+ String name,
+ String signature,
+ String superName,
+ String[] interfaces) {
+ cv1.visit(version, access, name, signature, superName, interfaces);
+ cv2.visit(version, access, name, signature, superName, interfaces);
+ }
+
+ public void visitEnd() {
+ cv1.visitEnd();
+ cv2.visitEnd();
+ cv1 = cv2 = null;
+ }
+
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ cv1.visitInnerClass(name, outerName, innerName, access);
+ cv2.visitInnerClass(name, outerName, innerName, access);
+ }
+
+ public FieldVisitor visitField(int access,
+ String name,
+ String desc,
+ String signature,
+ Object value) {
+ FieldVisitor fv1 = cv1.visitField(access, name, desc, signature, value);
+ FieldVisitor fv2 = cv2.visitField(access, name, desc, signature, value);
+ if (fv1 == null)
+ return fv2;
+ if (fv2 == null)
+ return fv1;
+ return new FieldVisitorTee(fv1, fv2);
+ }
+
+
+ public MethodVisitor visitMethod(int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ MethodVisitor mv1 = cv1.visitMethod(access, name, desc, signature, exceptions);
+ MethodVisitor mv2 = cv2.visitMethod(access, name, desc, signature, exceptions);
+ if (mv1 == null)
+ return mv2;
+ if (mv2 == null)
+ return mv1;
+ return new MethodVisitorTee(mv1, mv2);
+ }
+
+ public void visitSource(String source, String debug) {
+ cv1.visitSource(source, debug);
+ cv2.visitSource(source, debug);
+ }
+
+ public void visitOuterClass(String owner, String name, String desc) {
+ cv1.visitOuterClass(owner, name, desc);
+ cv2.visitOuterClass(owner, name, desc);
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return AnnotationVisitorTee.getInstance(cv1.visitAnnotation(desc, visible),
+ cv2.visitAnnotation(desc, visible));
+ }
+
+ public void visitAttribute(Attribute attrs) {
+ cv1.visitAttribute(attrs);
+ cv2.visitAttribute(attrs);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/FieldVisitorTee.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/FieldVisitorTee.java
new file mode 100644
index 0000000..dc0461e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/FieldVisitorTee.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.FieldVisitor;
+
+public class FieldVisitorTee implements FieldVisitor {
+ private FieldVisitor fv1, fv2;
+
+ public FieldVisitorTee(FieldVisitor fv1, FieldVisitor fv2) {
+ this.fv1 = fv1;
+ this.fv2 = fv2;
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return AnnotationVisitorTee.getInstance(fv1.visitAnnotation(desc, visible),
+ fv2.visitAnnotation(desc, visible));
+ }
+
+ public void visitAttribute(Attribute attr) {
+ fv1.visitAttribute(attr);
+ fv2.visitAttribute(attr);
+ }
+
+ public void visitEnd() {
+ fv1.visitEnd();
+ fv2.visitEnd();
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilter.java
new file mode 100644
index 0000000..6180b4f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilter.java
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+public interface MethodFilter {
+ // TODO: pass class name too?
+ boolean accept(int access, String name, String desc, String signature, String[] exceptions);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilterTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilterTransformer.java
new file mode 100644
index 0000000..98eba93
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodFilterTransformer.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+public class MethodFilterTransformer extends AbstractClassTransformer {
+ private MethodFilter filter;
+ private ClassTransformer pass;
+ private ClassVisitor direct;
+
+ public MethodFilterTransformer(MethodFilter filter, ClassTransformer pass) {
+ this.filter = filter;
+ this.pass = pass;
+ super.setTarget(pass);
+ }
+
+ public MethodVisitor visitMethod(int access,
+ String name,
+ String desc,
+ String signature,
+ String[] exceptions) {
+ return (filter.accept(access, name, desc, signature, exceptions) ? pass : direct).visitMethod(access, name, desc, signature, exceptions);
+ }
+
+ public void setTarget(ClassVisitor target) {
+ pass.setTarget(target);
+ direct = target;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodVisitorTee.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodVisitorTee.java
new file mode 100644
index 0000000..0d5800c
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/MethodVisitorTee.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.AnnotationVisitor;
+import org.powermock.api.mockito.repackaged.asm.Attribute;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.MethodVisitor;
+
+public class MethodVisitorTee implements MethodVisitor {
+ private final MethodVisitor mv1;
+ private final MethodVisitor mv2;
+
+ public MethodVisitorTee(MethodVisitor mv1, MethodVisitor mv2) {
+ this.mv1 = mv1;
+ this.mv2 = mv2;
+ }
+
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack, Object[] stack) {
+ mv1.visitFrame(type, nLocal, local, nStack, stack);
+ mv2.visitFrame(type, nLocal, local, nStack, stack);
+ }
+
+ public AnnotationVisitor visitAnnotationDefault() {
+ return AnnotationVisitorTee.getInstance(mv1.visitAnnotationDefault(),
+ mv2.visitAnnotationDefault());
+ }
+
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ return AnnotationVisitorTee.getInstance(mv1.visitAnnotation(desc, visible),
+ mv2.visitAnnotation(desc, visible));
+ }
+
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc,
+ boolean visible) {
+ return AnnotationVisitorTee.getInstance(mv1.visitParameterAnnotation(parameter, desc, visible),
+ mv2.visitParameterAnnotation(parameter, desc, visible));
+ }
+
+ public void visitAttribute(Attribute attr) {
+ mv1.visitAttribute(attr);
+ mv2.visitAttribute(attr);
+ }
+
+ public void visitCode() {
+ mv1.visitCode();
+ mv2.visitCode();
+ }
+
+ public void visitInsn(int opcode) {
+ mv1.visitInsn(opcode);
+ mv2.visitInsn(opcode);
+ }
+
+ public void visitIntInsn(int opcode, int operand) {
+ mv1.visitIntInsn(opcode, operand);
+ mv2.visitIntInsn(opcode, operand);
+ }
+
+ public void visitVarInsn(int opcode, int var) {
+ mv1.visitVarInsn(opcode, var);
+ mv2.visitVarInsn(opcode, var);
+ }
+
+ public void visitTypeInsn(int opcode, String desc) {
+ mv1.visitTypeInsn(opcode, desc);
+ mv2.visitTypeInsn(opcode, desc);
+ }
+
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ mv1.visitFieldInsn(opcode, owner, name, desc);
+ mv2.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ mv1.visitMethodInsn(opcode, owner, name, desc);
+ mv2.visitMethodInsn(opcode, owner, name, desc);
+ }
+
+ public void visitJumpInsn(int opcode, Label label) {
+ mv1.visitJumpInsn(opcode, label);
+ mv2.visitJumpInsn(opcode, label);
+ }
+
+ public void visitLabel(Label label) {
+ mv1.visitLabel(label);
+ mv2.visitLabel(label);
+ }
+
+ public void visitLdcInsn(Object cst) {
+ mv1.visitLdcInsn(cst);
+ mv2.visitLdcInsn(cst);
+ }
+
+ public void visitIincInsn(int var, int increment) {
+ mv1.visitIincInsn(var, increment);
+ mv2.visitIincInsn(var, increment);
+ }
+
+ public void visitTableSwitchInsn(int min, int max, Label dflt, Label labels[]) {
+ mv1.visitTableSwitchInsn(min, max, dflt, labels);
+ mv2.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+
+ public void visitLookupSwitchInsn(Label dflt, int keys[], Label labels[]) {
+ mv1.visitLookupSwitchInsn(dflt, keys, labels);
+ mv2.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ mv1.visitMultiANewArrayInsn(desc, dims);
+ mv2.visitMultiANewArrayInsn(desc, dims);
+ }
+
+ public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
+ mv1.visitTryCatchBlock(start, end, handler, type);
+ mv2.visitTryCatchBlock(start, end, handler, type);
+ }
+
+ public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
+ mv1.visitLocalVariable(name, desc, signature, start, end, index);
+ mv2.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+
+ public void visitLineNumber(int line, Label start) {
+ mv1.visitLineNumber(line, start);
+ mv2.visitLineNumber(line, start);
+ }
+
+ public void visitMaxs(int maxStack, int maxLocals) {
+ mv1.visitMaxs(maxStack, maxLocals);
+ mv2.visitMaxs(maxStack, maxLocals);
+ }
+
+ public void visitEnd() {
+ mv1.visitEnd();
+ mv2.visitEnd();
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassGenerator.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassGenerator.java
new file mode 100644
index 0000000..5c87f49
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassGenerator.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassGenerator;
+
+public class TransformingClassGenerator implements ClassGenerator {
+ private ClassGenerator gen;
+ private ClassTransformer t;
+
+ public TransformingClassGenerator(ClassGenerator gen, ClassTransformer t) {
+ this.gen = gen;
+ this.t = t;
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ t.setTarget(v);
+ gen.generateClass(t);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassLoader.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassLoader.java
new file mode 100644
index 0000000..ab6272f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/TransformingClassLoader.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform;
+
+import org.powermock.api.mockito.repackaged.asm.ClassReader;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassGenerator;
+
+public class TransformingClassLoader extends AbstractClassLoader {
+ private ClassTransformerFactory t;
+
+ public TransformingClassLoader(ClassLoader parent, ClassFilter filter, ClassTransformerFactory t) {
+ super(parent, parent, filter);
+ this.t = t;
+ }
+
+ protected ClassGenerator getGenerator(ClassReader r) {
+ ClassTransformer t2 = (ClassTransformer)t.newInstance();
+ return new TransformingClassGenerator(super.getGenerator(r), t2);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AbstractInterceptFieldCallback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AbstractInterceptFieldCallback.java
new file mode 100644
index 0000000..add0ede
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AbstractInterceptFieldCallback.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+/**
+ * @author Chris Nokleberg
+ */
+public class AbstractInterceptFieldCallback implements InterceptFieldCallback {
+
+ public int writeInt(Object obj, String name, int oldValue, int newValue) { return newValue; }
+ public char writeChar(Object obj, String name, char oldValue, char newValue) { return newValue; }
+ public byte writeByte(Object obj, String name, byte oldValue, byte newValue) { return newValue; }
+ public boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue) { return newValue; }
+ public short writeShort(Object obj, String name, short oldValue, short newValue) { return newValue; }
+ public float writeFloat(Object obj, String name, float oldValue, float newValue) { return newValue; }
+ public double writeDouble(Object obj, String name, double oldValue, double newValue) { return newValue; }
+ public long writeLong(Object obj, String name, long oldValue, long newValue) { return newValue; }
+ public Object writeObject(Object obj, String name, Object oldValue, Object newValue) { return newValue; }
+
+ public int readInt(Object obj, String name, int oldValue) { return oldValue; }
+ public char readChar(Object obj, String name, char oldValue) { return oldValue; }
+ public byte readByte(Object obj, String name, byte oldValue) { return oldValue; }
+ public boolean readBoolean(Object obj, String name, boolean oldValue) { return oldValue; }
+ public short readShort(Object obj, String name, short oldValue) { return oldValue; }
+ public float readFloat(Object obj, String name, float oldValue) { return oldValue; }
+ public double readDouble(Object obj, String name, double oldValue) { return oldValue; }
+ public long readLong(Object obj, String name, long oldValue) { return oldValue; }
+ public Object readObject(Object obj, String name, Object oldValue) { return oldValue; }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AccessFieldTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AccessFieldTransformer.java
new file mode 100644
index 0000000..6f8dcc0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AccessFieldTransformer.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+public class AccessFieldTransformer extends ClassEmitterTransformer {
+ private Callback callback;
+
+ public AccessFieldTransformer(Callback callback) {
+ this.callback = callback;
+ }
+
+ public void declare_field(int access, final String name, Type type, Object value) {
+ super.declare_field(access, name, type, value);
+
+ String property = TypeUtils.upperFirst(callback.getPropertyName(getClassType(), name));
+ if (property != null) {
+ CodeEmitter e;
+ e = begin_method(Constants.ACC_PUBLIC,
+ new Signature("get" + property,
+ type,
+ Constants.TYPES_EMPTY),
+ null);
+ e.load_this();
+ e.getfield(name);
+ e.return_value();
+ e.end_method();
+
+ e = begin_method(Constants.ACC_PUBLIC,
+ new Signature("set" + property,
+ Type.VOID_TYPE,
+ new Type[]{ type }),
+ null);
+ e.load_this();
+ e.load_arg(0);
+ e.putfield(name);
+ e.return_value();
+ e.end_method();
+ }
+ }
+
+ public interface Callback {
+ String getPropertyName(Type owner, String fieldName);
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddDelegateTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddDelegateTransformer.java
new file mode 100644
index 0000000..98ce7e7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddDelegateTransformer.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * @author Juozas Baliuka
+ */
+public class AddDelegateTransformer extends ClassEmitterTransformer {
+ private static final String DELEGATE = "$CGLIB_DELEGATE";
+ private static final Signature CSTRUCT_OBJECT =
+ TypeUtils.parseSignature("void <init>(Object)");
+
+ private Class[] delegateIf;
+ private Class delegateImpl;
+ private Type delegateType;
+
+ /** Creates a new instance of AddDelegateTransformer */
+ public AddDelegateTransformer(Class delegateIf[], Class delegateImpl) {
+ try {
+ delegateImpl.getConstructor(new Class[]{ Object.class });
+ this.delegateIf = delegateIf;
+ this.delegateImpl = delegateImpl;
+ delegateType = Type.getType(delegateImpl);
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+
+ public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
+
+ if(!TypeUtils.isInterface(access)){
+
+ Type[] all = TypeUtils.add(interfaces, TypeUtils.getTypes(delegateIf));
+ super.begin_class(version, access, className, superType, all, sourceFile);
+
+ declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT,
+ DELEGATE,
+ delegateType,
+ null);
+ for (int i = 0; i < delegateIf.length; i++) {
+ Method[] methods = delegateIf[i].getMethods();
+ for (int j = 0; j < methods.length; j++) {
+ if (Modifier.isAbstract(methods[j].getModifiers())) {
+ addDelegate(methods[j]);
+ }
+ }
+ }
+ }else{
+ super.begin_class(version, access, className, superType, interfaces, sourceFile);
+ }
+ }
+
+ public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
+ final CodeEmitter e = super.begin_method(access, sig, exceptions);
+ if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
+ return new CodeEmitter(e) {
+ private boolean transformInit = true;
+ public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+ super.visitMethodInsn(opcode, owner, name, desc);
+ if (transformInit && opcode == Constants.INVOKESPECIAL) {
+ load_this();
+ new_instance(delegateType);
+ dup();
+ load_this();
+ invoke_constructor(delegateType, CSTRUCT_OBJECT);
+ putfield(DELEGATE);
+ transformInit = false;
+ }
+ }
+ };
+ }
+ return e;
+ }
+
+ private void addDelegate(Method m) {
+ Method delegate;
+ try {
+ delegate = delegateImpl.getMethod(m.getName(), m.getParameterTypes());
+ if (!delegate.getReturnType().getName().equals(m.getReturnType().getName())){
+ throw new IllegalArgumentException("Invalid delegate signature " + delegate);
+ }
+ } catch (NoSuchMethodException e) {
+ throw new CodeGenerationException(e);
+ }
+
+ final Signature sig = ReflectUtils.getSignature(m);
+ Type[] exceptions = TypeUtils.getTypes(m.getExceptionTypes());
+ CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, sig, exceptions);
+ e.load_this();
+ e.getfield(DELEGATE);
+ e.load_args();
+ e.invoke_virtual(delegateType, sig);
+ e.return_value();
+ e.end_method();
+ }
+}
+
+
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddInitTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddInitTransformer.java
new file mode 100644
index 0000000..9fa2eb2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddInitTransformer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Mark Hobson
+ */
+public class AddInitTransformer extends ClassEmitterTransformer {
+ private MethodInfo info;
+
+ public AddInitTransformer(Method method) {
+ info = ReflectUtils.getMethodInfo(method);
+
+ Type[] types = info.getSignature().getArgumentTypes();
+ if (types.length != 1 ||
+ !types[0].equals(Constants.TYPE_OBJECT) ||
+ !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) {
+ throw new IllegalArgumentException(method + " illegal signature");
+ }
+ }
+
+ public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
+ final CodeEmitter emitter = super.begin_method(access, sig, exceptions);
+ if (sig.getName().equals(Constants.CONSTRUCTOR_NAME)) {
+ return new CodeEmitter(emitter) {
+ public void visitInsn(int opcode) {
+ if (opcode == Constants.RETURN) {
+ load_this();
+ invoke(info);
+ }
+ super.visitInsn(opcode);
+ }
+ };
+ }
+ return emitter;
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddPropertyTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddPropertyTransformer.java
new file mode 100644
index 0000000..8434850
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddPropertyTransformer.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.util.Map;
+
+public class AddPropertyTransformer extends ClassEmitterTransformer {
+ private final String[] names;
+ private final Type[] types;
+
+ public AddPropertyTransformer(Map props) {
+ int size = props.size();
+ names = (String[])props.keySet().toArray(new String[size]);
+ types = new Type[size];
+ for (int i = 0; i < size; i++) {
+ types[i] = (Type)props.get(names[i]);
+ }
+ }
+
+ public AddPropertyTransformer(String[] names, Type[] types) {
+ this.names = names;
+ this.types = types;
+ }
+
+ public void end_class() {
+ if (!TypeUtils.isAbstract(getAccess())) {
+ EmitUtils.add_properties(this, names, types);
+ }
+ super.end_class();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddStaticInitTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddStaticInitTransformer.java
new file mode 100644
index 0000000..f667485
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/AddStaticInitTransformer.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.MethodInfo;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Juozas Baliuka, Chris Nokleberg
+ */
+public class AddStaticInitTransformer extends ClassEmitterTransformer {
+ private MethodInfo info;
+
+ public AddStaticInitTransformer(Method classInit) {
+ info = ReflectUtils.getMethodInfo(classInit);
+ if (!TypeUtils.isStatic(info.getModifiers())) {
+ throw new IllegalArgumentException(classInit + " is not static");
+ }
+ Type[] types = info.getSignature().getArgumentTypes();
+ if (types.length != 1 ||
+ !types[0].equals(Constants.TYPE_CLASS) ||
+ !info.getSignature().getReturnType().equals(Type.VOID_TYPE)) {
+ throw new IllegalArgumentException(classInit + " illegal signature");
+ }
+ }
+
+ protected void init() {
+ if (!TypeUtils.isInterface(getAccess())) {
+ CodeEmitter e = getStaticHook();
+ EmitUtils.load_class_this(e);
+ e.invoke(info);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProvider.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProvider.java
new file mode 100644
index 0000000..a75f565
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProvider.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+public interface FieldProvider {
+
+ String[] getFieldNames();
+
+ Class[] getFieldTypes();
+
+ void setField(int index, Object value);
+
+ Object getField(int index);
+
+
+ void setField(String name, Object value);
+
+ Object getField(String name);
+
+
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProviderTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProviderTransformer.java
new file mode 100644
index 0000000..4901a5f
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/FieldProviderTransformer.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeGenerationException;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ProcessSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FieldProviderTransformer extends ClassEmitterTransformer {
+
+ private static final String FIELD_NAMES = "CGLIB$FIELD_NAMES";
+ private static final String FIELD_TYPES = "CGLIB$FIELD_TYPES";
+
+ private static final Type FIELD_PROVIDER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.transform.impl.FieldProvider");
+ private static final Type ILLEGAL_ARGUMENT_EXCEPTION =
+ TypeUtils.parseType("IllegalArgumentException");
+ private static final Signature PROVIDER_GET =
+ TypeUtils.parseSignature("Object getField(String)");
+ private static final Signature PROVIDER_SET =
+ TypeUtils.parseSignature("void setField(String, Object)");
+ private static final Signature PROVIDER_SET_BY_INDEX =
+ TypeUtils.parseSignature("void setField(int, Object)");
+ private static final Signature PROVIDER_GET_BY_INDEX =
+ TypeUtils.parseSignature("Object getField(int)");
+ private static final Signature PROVIDER_GET_TYPES =
+ TypeUtils.parseSignature("Class[] getFieldTypes()");
+ private static final Signature PROVIDER_GET_NAMES =
+ TypeUtils.parseSignature("String[] getFieldNames()");
+
+ private int access;
+ private Map fields;
+
+ public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
+ if (!TypeUtils.isAbstract(access)) {
+ interfaces = TypeUtils.add(interfaces, FIELD_PROVIDER);
+ }
+ this.access = access;
+ fields = new HashMap();
+ super.begin_class(version, access, className, superType, interfaces, sourceFile);
+ }
+
+ public void declare_field(int access, String name, Type type, Object value) {
+ super.declare_field(access, name, type, value);
+
+ if (!TypeUtils.isStatic(access)) {
+ fields.put(name, type);
+ }
+ }
+
+ public void end_class() {
+ if (!TypeUtils.isInterface(access)) {
+ try {
+ generate();
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new CodeGenerationException(e);
+ }
+ }
+ super.end_class();
+ }
+
+ private void generate() throws Exception {
+ final String[] names = (String[])fields.keySet().toArray(new String[fields.size()]);
+
+ int indexes[] = new int[names.length];
+ for (int i = 0; i < indexes.length; i++) {
+ indexes[i] = i;
+ }
+
+ super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_NAMES, Constants.TYPE_STRING_ARRAY, null);
+ super.declare_field(Constants.PRIVATE_FINAL_STATIC, FIELD_TYPES, Constants.TYPE_CLASS_ARRAY, null);
+
+ // use separate methods here because each process switch inner class needs a final CodeEmitter
+ initFieldProvider(names);
+ getNames();
+ getTypes();
+ getField(names);
+ setField(names);
+ setByIndex(names, indexes);
+ getByIndex(names, indexes);
+ }
+
+ private void initFieldProvider(String[] names) {
+ CodeEmitter e = getStaticHook();
+ EmitUtils.push_object(e, names);
+ e.putstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY);
+
+ e.push(names.length);
+ e.newarray(Constants.TYPE_CLASS);
+ e.dup();
+ for(int i = 0; i < names.length; i++ ){
+ e.dup();
+ e.push(i);
+ Type type = (Type)fields.get(names[i]);
+ EmitUtils.load_class(e, type);
+ e.aastore();
+ }
+ e.putstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY);
+ }
+
+ private void getNames() {
+ CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_NAMES, null);
+ e.getstatic(getClassType(), FIELD_NAMES, Constants.TYPE_STRING_ARRAY);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void getTypes() {
+ CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_TYPES, null);
+ e.getstatic(getClassType(), FIELD_TYPES, Constants.TYPE_CLASS_ARRAY);
+ e.return_value();
+ e.end_method();
+ }
+
+ private void setByIndex(final String[] names, final int[] indexes) throws Exception {
+ final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_SET_BY_INDEX, null);
+ e.load_this();
+ e.load_arg(1);
+ e.load_arg(0);
+ e.process_switch(indexes, new ProcessSwitchCallback() {
+ public void processCase(int key, Label end) throws Exception {
+ Type type = (Type)fields.get(names[key]);
+ e.unbox(type);
+ e.putfield(names[key]);
+ e.return_value();
+ }
+ public void processDefault() throws Exception {
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index");
+ }
+ });
+ e.end_method();
+ }
+
+ private void getByIndex(final String[] names, final int[] indexes) throws Exception {
+ final CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC, PROVIDER_GET_BY_INDEX, null);
+ e.load_this();
+ e.load_arg(0);
+ e.process_switch(indexes, new ProcessSwitchCallback() {
+ public void processCase(int key, Label end) throws Exception {
+ Type type = (Type)fields.get(names[key]);
+ e.getfield(names[key]);
+ e.box(type);
+ e.return_value();
+ }
+ public void processDefault() throws Exception {
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field index");
+ }
+ });
+ e.end_method();
+ }
+
+ // TODO: if this is used to enhance class files SWITCH_STYLE_TRIE should be used
+ // to avoid JVM hashcode implementation incompatibilities
+ private void getField(String[] names) throws Exception {
+ final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_GET, null);
+ e.load_this();
+ e.load_arg(0);
+ EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ Type type = (Type)fields.get(key);
+ e.getfield((String)key);
+ e.box(type);
+ e.return_value();
+ }
+ public void processDefault() {
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name");
+ }
+ });
+ e.end_method();
+ }
+
+ private void setField(String[] names) throws Exception {
+ final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, PROVIDER_SET, null);
+ e.load_this();
+ e.load_arg(1);
+ e.load_arg(0);
+ EmitUtils.string_switch(e, names, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ Type type = (Type)fields.get(key);
+ e.unbox(type);
+ e.putfield((String)key);
+ e.return_value();
+ }
+ public void processDefault() {
+ e.throw_exception(ILLEGAL_ARGUMENT_EXCEPTION, "Unknown field name");
+ }
+ });
+ e.end_method();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldCallback.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldCallback.java
new file mode 100644
index 0000000..5e0ac65
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldCallback.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+/**
+ * @author Juozas Baliuka
+ */
+public interface InterceptFieldCallback {
+
+ int writeInt(Object obj, String name, int oldValue, int newValue);
+ char writeChar(Object obj, String name, char oldValue, char newValue);
+ byte writeByte(Object obj, String name, byte oldValue, byte newValue);
+ boolean writeBoolean(Object obj, String name, boolean oldValue, boolean newValue);
+ short writeShort(Object obj, String name, short oldValue, short newValue);
+ float writeFloat(Object obj, String name, float oldValue, float newValue);
+ double writeDouble(Object obj, String name, double oldValue, double newValue);
+ long writeLong(Object obj, String name, long oldValue, long newValue);
+ Object writeObject(Object obj, String name, Object oldValue, Object newValue);
+
+ int readInt(Object obj, String name, int oldValue);
+ char readChar(Object obj, String name, char oldValue);
+ byte readByte(Object obj, String name, byte oldValue);
+ boolean readBoolean(Object obj, String name, boolean oldValue);
+ short readShort(Object obj, String name, short oldValue);
+ float readFloat(Object obj, String name, float oldValue);
+ double readDouble(Object obj, String name, double oldValue);
+ long readLong(Object obj, String name, long oldValue);
+ Object readObject(Object obj, String name, Object oldValue);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldEnabled.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldEnabled.java
new file mode 100644
index 0000000..050077a
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldEnabled.java
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+public interface InterceptFieldEnabled {
+ InterceptFieldCallback getInterceptFieldCallback();
+
+ void setInterceptFieldCallback(InterceptFieldCallback callback);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldFilter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldFilter.java
new file mode 100644
index 0000000..a8f43f5
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldFilter.java
@@ -0,0 +1,12 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+
+public interface InterceptFieldFilter {
+ boolean acceptRead(Type owner, String name);
+ boolean acceptWrite(Type owner, String name);
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldTransformer.java
new file mode 100644
index 0000000..1fac3ad
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/InterceptFieldTransformer.java
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+/**
+ * @author Juozas Baliuka, Chris Nokleberg
+ */
+public class InterceptFieldTransformer extends ClassEmitterTransformer {
+ private static final String CALLBACK_FIELD = "$CGLIB_READ_WRITE_CALLBACK";
+ private static final Type CALLBACK =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.transform.impl.InterceptFieldCallback");
+ private static final Type ENABLED =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.transform.impl.InterceptFieldEnabled");
+ private static final Signature ENABLED_SET =
+ new Signature("setInterceptFieldCallback", Type.VOID_TYPE, new Type[]{ CALLBACK });
+ private static final Signature ENABLED_GET =
+ new Signature("getInterceptFieldCallback", CALLBACK, new Type[0]);
+
+ private InterceptFieldFilter filter;
+
+ public InterceptFieldTransformer(InterceptFieldFilter filter) {
+ this.filter = filter;
+ }
+
+ private static Signature readMethodSig(String name, String desc) {
+ return new Signature("$cglib_read_" + name, "()" + desc);
+ }
+
+ private static Signature writeMethodSig(String name, String desc) {
+ return new Signature("$cglib_write_" + name, "(" + desc + ")V");
+ }
+
+ private static Signature readCallbackSig(Type type) {
+ Type remap = remap(type);
+ return new Signature("read" + callbackName(remap),
+ remap,
+ new Type[]{ Constants.TYPE_OBJECT,
+ Constants.TYPE_STRING,
+ remap });
+ }
+
+ private static Signature writeCallbackSig(Type type) {
+ Type remap = remap(type);
+ return new Signature("write" + callbackName(remap),
+ remap,
+ new Type[]{ Constants.TYPE_OBJECT,
+ Constants.TYPE_STRING,
+ remap,
+ remap });
+ }
+
+ private static Type remap(Type type) {
+ switch (type.getSort()) {
+ case Type.OBJECT:
+ case Type.ARRAY:
+ return Constants.TYPE_OBJECT;
+ default:
+ return type;
+ }
+ }
+
+ private static String callbackName(Type type) {
+ return (type == Constants.TYPE_OBJECT) ?
+ "Object" :
+ TypeUtils.upperFirst(TypeUtils.getClassName(type));
+ }
+
+ public void begin_class(int version, int access, String className, Type superType, Type[] interfaces, String sourceFile) {
+ if (!TypeUtils.isInterface(access)) {
+ super.begin_class(version, access, className, superType, TypeUtils.add(interfaces, ENABLED), sourceFile);
+
+ super.declare_field(Constants.ACC_PRIVATE | Constants.ACC_TRANSIENT,
+ CALLBACK_FIELD,
+ CALLBACK,
+ null);
+
+ CodeEmitter e;
+ e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_GET, null);
+ e.load_this();
+ e.getfield(CALLBACK_FIELD);
+ e.return_value();
+ e.end_method();
+
+ e = super.begin_method(Constants.ACC_PUBLIC, ENABLED_SET, null);
+ e.load_this();
+ e.load_arg(0);
+ e.putfield(CALLBACK_FIELD);
+ e.return_value();
+ e.end_method();
+ } else {
+ super.begin_class(version, access, className, superType, interfaces, sourceFile);
+ }
+ }
+
+ public void declare_field(int access, String name, Type type, Object value) {
+ super.declare_field(access, name, type, value);
+ if (!TypeUtils.isStatic(access)) {
+ if (filter.acceptRead(getClassType(), name)) {
+ addReadMethod(name, type);
+ }
+ if (filter.acceptWrite(getClassType(), name)) {
+ addWriteMethod(name, type);
+ }
+ }
+ }
+
+ private void addReadMethod(String name, Type type) {
+ CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC,
+ readMethodSig(name, type.getDescriptor()),
+ null);
+ e.load_this();
+ e.getfield(name);
+ e.load_this();
+ e.invoke_interface(ENABLED,ENABLED_GET);
+ Label intercept = e.make_label();
+ e.ifnonnull(intercept);
+ e.return_value();
+
+ e.mark(intercept);
+ Local result = e.make_local(type);
+ e.store_local(result);
+ e.load_this();
+ e.invoke_interface(ENABLED,ENABLED_GET);
+ e.load_this();
+ e.push(name);
+ e.load_local(result);
+ e.invoke_interface(CALLBACK, readCallbackSig(type));
+ if (!TypeUtils.isPrimitive(type)) {
+ e.checkcast(type);
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ private void addWriteMethod(String name, Type type) {
+ CodeEmitter e = super.begin_method(Constants.ACC_PUBLIC,
+ writeMethodSig(name, type.getDescriptor()),
+ null);
+ e.load_this();
+ e.dup();
+ e.invoke_interface(ENABLED,ENABLED_GET);
+ Label skip = e.make_label();
+ e.ifnull(skip);
+
+ e.load_this();
+ e.invoke_interface(ENABLED,ENABLED_GET);
+ e.load_this();
+ e.push(name);
+ e.load_this();
+ e.getfield(name);
+ e.load_arg(0);
+ e.invoke_interface(CALLBACK, writeCallbackSig(type));
+ if (!TypeUtils.isPrimitive(type)) {
+ e.checkcast(type);
+ }
+ Label go = e.make_label();
+ e.goTo(go);
+ e.mark(skip);
+ e.load_arg(0);
+ e.mark(go);
+ e.putfield(name);
+ e.return_value();
+ e.end_method();
+ }
+
+ public CodeEmitter begin_method(int access, Signature sig, Type[] exceptions) {
+ return new CodeEmitter(super.begin_method(access, sig, exceptions)) {
+ public void visitFieldInsn(int opcode, String owner, String name, String desc) {
+ Type towner = TypeUtils.fromInternalName(owner);
+ switch (opcode) {
+ case Constants.GETFIELD:
+ if (filter.acceptRead(towner, name)) {
+ helper(towner, readMethodSig(name, desc));
+ return;
+ }
+ break;
+ case Constants.PUTFIELD:
+ if (filter.acceptWrite(towner, name)) {
+ helper(towner, writeMethodSig(name, desc));
+ return;
+ }
+ break;
+ }
+ super.visitFieldInsn(opcode, owner, name, desc);
+ }
+
+ private void helper(Type owner, Signature sig) {
+ invoke_virtual(owner, sig);
+ }
+ };
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableStrategy.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableStrategy.java
new file mode 100644
index 0000000..733a2b0
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableStrategy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.cglib.core.ClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.DefaultGeneratorStrategy;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassTransformer;
+import org.powermock.api.mockito.repackaged.cglib.transform.MethodFilter;
+import org.powermock.api.mockito.repackaged.cglib.transform.MethodFilterTransformer;
+import org.powermock.api.mockito.repackaged.cglib.transform.TransformingClassGenerator;
+
+/**
+ * A {@link org.powermock.api.mockito.repackaged.cglib.core.GeneratorStrategy} suitable for use with {@link org.powermock.api.mockito.repackaged.cglib.proxy.Enhancer} which
+ * causes all undeclared exceptions thrown from within a proxied method to be wrapped
+ * in an alternative exception of your choice.
+ */
+public class UndeclaredThrowableStrategy extends DefaultGeneratorStrategy {
+ private static final MethodFilter TRANSFORM_FILTER = new MethodFilter() {
+ public boolean accept(int access, String name, String desc, String signature, String[] exceptions) {
+ return !TypeUtils.isPrivate(access) && name.indexOf('$') < 0;
+ }
+ };
+ private ClassTransformer t;
+
+ /**
+ * Create a new instance of this strategy.
+ * @param wrapper a class which extends either directly or
+ * indirectly from <code>Throwable</code> and which has at least one
+ * constructor that takes a single argument of type
+ * <code>Throwable</code>, for example
+ * <code>java.lang.reflect.UndeclaredThrowableException.class</code>
+ */
+ public UndeclaredThrowableStrategy(Class wrapper) {
+ t = new UndeclaredThrowableTransformer(wrapper);
+ t = new MethodFilterTransformer(TRANSFORM_FILTER, t);
+ }
+
+ protected ClassGenerator transform(ClassGenerator cg) throws Exception {
+ return new TransformingClassGenerator(cg, t);
+ }
+}
+
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableTransformer.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableTransformer.java
new file mode 100644
index 0000000..d88e374
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/transform/impl/UndeclaredThrowableTransformer.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.transform.impl;
+
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.Block;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+import org.powermock.api.mockito.repackaged.cglib.transform.ClassEmitterTransformer;
+
+import java.lang.reflect.Constructor;
+
+public class UndeclaredThrowableTransformer extends ClassEmitterTransformer {
+ private Type wrapper;
+
+ public UndeclaredThrowableTransformer(Class wrapper) {
+ this.wrapper = Type.getType(wrapper);
+ boolean found = false;
+ Constructor[] cstructs = wrapper.getConstructors();
+ for (int i = 0; i < cstructs.length; i++) {
+ Class[] types = cstructs[i].getParameterTypes();
+ if (types.length == 1 && types[0].equals(Throwable.class)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ throw new IllegalArgumentException(wrapper + " does not have a single-arg constructor that takes a Throwable");
+ }
+
+ public CodeEmitter begin_method(int access, final Signature sig, final Type[] exceptions) {
+ CodeEmitter e = super.begin_method(access, sig, exceptions);
+ if (TypeUtils.isAbstract(access) || sig.equals(Constants.SIG_STATIC)) {
+ return e;
+ }
+ return new CodeEmitter(e) {
+ private Block handler;
+ /* init */ {
+ handler = begin_block();
+ }
+ public void visitMaxs(int maxStack, int maxLocals) {
+ handler.end();
+ EmitUtils.wrap_undeclared_throwable(this, handler, exceptions, wrapper);
+ super.visitMaxs(maxStack, maxLocals);
+ }
+ };
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorter.java
new file mode 100644
index 0000000..33c7af9
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorter.java
@@ -0,0 +1,283 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.util;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassesKey;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+
+import java.util.Comparator;
+
+/**
+ * For the efficient sorting of multiple arrays in parallel.
+ * <p>
+ * Given two arrays of equal length and varying types, the standard
+ * technique for sorting them in parallel is to create a new temporary
+ * object for each row, store the objects in a temporary array, sort the
+ * array using a custom comparator, and the extract the original values
+ * back into their respective arrays. This is wasteful in both time and
+ * memory.
+ * <p>
+ * This class generates bytecode customized to the particular set of
+ * arrays you need to sort, in such a way that both arrays are sorted
+ * in-place, simultaneously.
+ * <p>
+ * Two sorting algorithms are provided.
+ * Quicksort is best when you only need to sort by a single column, as
+ * it requires very few comparisons and swaps. Mergesort is best used
+ * when sorting multiple columns, as it is a "stable" sort--that is, it
+ * does not affect the relative order of equal objects from previous sorts.
+ * <p>
+ * The mergesort algorithm here is an "in-place" variant, which while
+ * slower, does not require a temporary array.
+ *
+ * @author Chris Nokleberg
+ */
+abstract public class ParallelSorter extends SorterTemplate {
+ protected Object[] a;
+ private Comparer comparer;
+
+ protected ParallelSorter() {
+ }
+
+ /**
+ * Create a new ParallelSorter object for a set of arrays. You may
+ * sort the arrays multiple times via the same ParallelSorter object.
+ * @param arrays An array of arrays to sort. The arrays may be a mix
+ * of primitive and non-primitive types, but should all be the same
+ * length.
+ */
+ public static ParallelSorter create(Object[] arrays) {
+ Generator gen = new Generator();
+ gen.setArrays(arrays);
+ return gen.create();
+ }
+
+ abstract public ParallelSorter newInstance(Object[] arrays);
+
+ private int len() {
+ return ((Object[])a[0]).length;
+ }
+
+ /**
+ * Sort the arrays using the quicksort algorithm.
+ * @param index array (column) to sort by
+ */
+ public void quickSort(int index) {
+ quickSort(index, 0, len(), null);
+ }
+
+ /**
+ * Sort the arrays using the quicksort algorithm.
+ * @param index array (column) to sort by
+ * @param lo starting array index (row), inclusive
+ * @param hi ending array index (row), exclusive
+ */
+ public void quickSort(int index, int lo, int hi) {
+ quickSort(index, lo, hi, null);
+ }
+
+ /**
+ * Sort the arrays using the quicksort algorithm.
+ * @param index array (column) to sort by
+ * @param cmp Comparator to use if the specified column is non-primitive
+ */
+ public void quickSort(int index, Comparator cmp) {
+ quickSort(index, 0, len(), cmp);
+ }
+
+ /**
+ * Sort the arrays using the quicksort algorithm.
+ * @param index array (column) to sort by
+ * @param lo starting array index (row), inclusive
+ * @param hi ending array index (row), exclusive
+ * @param cmp Comparator to use if the specified column is non-primitive
+ */
+ public void quickSort(int index, int lo, int hi, Comparator cmp) {
+ chooseComparer(index, cmp);
+ super.quickSort(lo, hi - 1);
+ }
+
+ /**
+ * @param index array (column) to sort by
+ */
+ public void mergeSort(int index) {
+ mergeSort(index, 0, len(), null);
+ }
+
+ /**
+ * Sort the arrays using an in-place merge sort.
+ * @param index array (column) to sort by
+ * @param lo starting array index (row), inclusive
+ * @param hi ending array index (row), exclusive
+ */
+ public void mergeSort(int index, int lo, int hi) {
+ mergeSort(index, lo, hi, null);
+ }
+
+ /**
+ * Sort the arrays using an in-place merge sort.
+ * @param index array (column) to sort by
+ * @param cmp
+ */
+ public void mergeSort(int index, Comparator cmp) {
+ mergeSort(index, 0, len(), cmp);
+ }
+
+ /**
+ * Sort the arrays using an in-place merge sort.
+ * @param index array (column) to sort by
+ * @param lo starting array index (row), inclusive
+ * @param hi ending array index (row), exclusive
+ * @param cmp Comparator to use if the specified column is non-primitive
+ */
+ public void mergeSort(int index, int lo, int hi, Comparator cmp) {
+ chooseComparer(index, cmp);
+ super.mergeSort(lo, hi - 1);
+ }
+
+ private void chooseComparer(int index, Comparator cmp) {
+ Object array = a[index];
+ Class type = array.getClass().getComponentType();
+ if (type.equals(Integer.TYPE)) {
+ comparer = new IntComparer((int[])array);
+ } else if (type.equals(Long.TYPE)) {
+ comparer = new LongComparer((long[])array);
+ } else if (type.equals(Double.TYPE)) {
+ comparer = new DoubleComparer((double[])array);
+ } else if (type.equals(Float.TYPE)) {
+ comparer = new FloatComparer((float[])array);
+ } else if (type.equals(Short.TYPE)) {
+ comparer = new ShortComparer((short[])array);
+ } else if (type.equals(Byte.TYPE)) {
+ comparer = new ByteComparer((byte[])array);
+ } else if (cmp != null) {
+ comparer = new ComparatorComparer((Object[])array, cmp);
+ } else {
+ comparer = new ObjectComparer((Object[])array);
+ }
+ }
+
+ protected int compare(int i, int j) {
+ return comparer.compare(i, j);
+ }
+
+ interface Comparer {
+ int compare(int i, int j);
+ }
+
+ static class ComparatorComparer implements Comparer {
+ private Object[] a;
+ private Comparator cmp;
+
+ public ComparatorComparer(Object[] a, Comparator cmp) {
+ this.a = a;
+ this.cmp = cmp;
+ }
+
+ public int compare(int i, int j) {
+ return cmp.compare(a[i], a[j]);
+ }
+ }
+
+ static class ObjectComparer implements Comparer {
+ private Object[] a;
+ public ObjectComparer(Object[] a) { this.a = a; }
+ public int compare(int i, int j) {
+ return ((Comparable)a[i]).compareTo(a[j]);
+ }
+ }
+
+ static class IntComparer implements Comparer {
+ private int[] a;
+ public IntComparer(int[] a) { this.a = a; }
+ public int compare(int i, int j) { return a[i] - a[j]; }
+ }
+
+ static class LongComparer implements Comparer {
+ private long[] a;
+ public LongComparer(long[] a) { this.a = a; }
+ public int compare(int i, int j) {
+ long vi = a[i];
+ long vj = a[j];
+ return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
+ }
+ }
+
+ static class FloatComparer implements Comparer {
+ private float[] a;
+ public FloatComparer(float[] a) { this.a = a; }
+ public int compare(int i, int j) {
+ float vi = a[i];
+ float vj = a[j];
+ return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
+ }
+ }
+
+ static class DoubleComparer implements Comparer {
+ private double[] a;
+ public DoubleComparer(double[] a) { this.a = a; }
+ public int compare(int i, int j) {
+ double vi = a[i];
+ double vj = a[j];
+ return (vi == vj) ? 0 : (vi > vj) ? 1 : -1;
+ }
+ }
+
+ static class ShortComparer implements Comparer {
+ private short[] a;
+ public ShortComparer(short[] a) { this.a = a; }
+ public int compare(int i, int j) { return a[i] - a[j]; }
+ }
+
+ static class ByteComparer implements Comparer {
+ private byte[] a;
+ public ByteComparer(byte[] a) { this.a = a; }
+ public int compare(int i, int j) { return a[i] - a[j]; }
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(ParallelSorter.class.getName());
+
+ private Object[] arrays;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return null; // TODO
+ }
+
+ public void setArrays(Object[] arrays) {
+ this.arrays = arrays;
+ }
+
+ public ParallelSorter create() {
+ return (ParallelSorter)super.create(ClassesKey.create(arrays));
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ if (arrays.length == 0) {
+ throw new IllegalArgumentException("No arrays specified to sort");
+ }
+ for (int i = 0; i < arrays.length; i++) {
+ if (!arrays[i].getClass().isArray()) {
+ throw new IllegalArgumentException(arrays[i].getClass() + " is not an array");
+ }
+ }
+ new ParallelSorterEmitter(v, getClassName(), arrays);
+ }
+
+ protected Object firstInstance(Class type) {
+ return ((ParallelSorter) ReflectUtils.newInstance(type)).newInstance(arrays);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return ((ParallelSorter)instance).newInstance(arrays);
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorterEmitter.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorterEmitter.java
new file mode 100644
index 0000000..c4a223e
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/ParallelSorterEmitter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.util;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Local;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+class ParallelSorterEmitter extends ClassEmitter {
+ private static final Type PARALLEL_SORTER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.util.ParallelSorter");
+ private static final Signature CSTRUCT_OBJECT_ARRAY =
+ TypeUtils.parseConstructor("Object[]");
+ private static final Signature NEW_INSTANCE =
+ new Signature("newInstance", PARALLEL_SORTER, new Type[]{ Constants.TYPE_OBJECT_ARRAY });
+ private static final Signature SWAP =
+ TypeUtils.parseSignature("void swap(int, int)");
+
+ public ParallelSorterEmitter(ClassVisitor v, String className, Object[] arrays) {
+ super(v);
+ begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, PARALLEL_SORTER, null, Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(this);
+ EmitUtils.factory_method(this, NEW_INSTANCE);
+ generateConstructor(arrays);
+ generateSwap(arrays);
+ end_class();
+ }
+
+ private String getFieldName(int index) {
+ return "FIELD_" + index;
+ }
+
+ private void generateConstructor(Object[] arrays) {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT_ARRAY, null);
+ e.load_this();
+ e.super_invoke_constructor();
+ e.load_this();
+ e.load_arg(0);
+ e.super_putfield("a", Constants.TYPE_OBJECT_ARRAY);
+ for (int i = 0; i < arrays.length; i++) {
+ Type type = Type.getType(arrays[i].getClass());
+ declare_field(Constants.ACC_PRIVATE, getFieldName(i), type, null);
+ e.load_this();
+ e.load_arg(0);
+ e.push(i);
+ e.aaload();
+ e.checkcast(type);
+ e.putfield(getFieldName(i));
+ }
+ e.return_value();
+ e.end_method();
+ }
+
+ private void generateSwap(final Object[] arrays) {
+ CodeEmitter e = begin_method(Constants.ACC_PUBLIC, SWAP, null);
+ for (int i = 0; i < arrays.length; i++) {
+ Type type = Type.getType(arrays[i].getClass());
+ Type component = TypeUtils.getComponentType(type);
+ Local T = e.make_local(type);
+
+ e.load_this();
+ e.getfield(getFieldName(i));
+ e.store_local(T);
+
+ e.load_local(T);
+ e.load_arg(0);
+
+ e.load_local(T);
+ e.load_arg(1);
+ e.array_load(component);
+
+ e.load_local(T);
+ e.load_arg(1);
+
+ e.load_local(T);
+ e.load_arg(0);
+ e.array_load(component);
+
+ e.array_store(component);
+ e.array_store(component);
+ }
+ e.return_value();
+ e.end_method();
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/SorterTemplate.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/SorterTemplate.java
new file mode 100644
index 0000000..90df836
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/SorterTemplate.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.util;
+
+abstract class SorterTemplate {
+ private static final int MERGESORT_THRESHOLD = 12;
+ private static final int QUICKSORT_THRESHOLD = 7;
+
+ abstract protected void swap(int i, int j);
+ abstract protected int compare(int i, int j);
+
+ protected void quickSort(int lo, int hi) {
+ quickSortHelper(lo, hi);
+ insertionSort(lo, hi);
+ }
+
+ private void quickSortHelper(int lo, int hi) {
+ for (;;) {
+ int diff = hi - lo;
+ if (diff <= QUICKSORT_THRESHOLD) {
+ break;
+ }
+ int i = (hi + lo) / 2;
+ if (compare(lo, i) > 0) {
+ swap(lo, i);
+ }
+ if (compare(lo, hi) > 0) {
+ swap(lo, hi);
+ }
+ if (compare(i, hi) > 0) {
+ swap(i, hi);
+ }
+ int j = hi - 1;
+ swap(i, j);
+ i = lo;
+ int v = j;
+ for (;;) {
+ while (compare(++i, v) < 0) {
+ /* nothing */;
+ }
+ while (compare(--j, v) > 0) {
+ /* nothing */;
+ }
+ if (j < i) {
+ break;
+ }
+ swap(i, j);
+ }
+ swap(i, hi - 1);
+ if (j - lo <= hi - i + 1) {
+ quickSortHelper(lo, j);
+ lo = i + 1;
+ } else {
+ quickSortHelper(i + 1, hi);
+ hi = j;
+ }
+ }
+ }
+
+ private void insertionSort(int lo, int hi) {
+ for (int i = lo + 1 ; i <= hi; i++) {
+ for (int j = i; j > lo; j--) {
+ if (compare(j - 1, j) > 0) {
+ swap(j - 1, j);
+ } else {
+ break;
+ }
+ }
+ }
+ }
+
+ protected void mergeSort(int lo, int hi) {
+ int diff = hi - lo;
+ if (diff <= MERGESORT_THRESHOLD) {
+ insertionSort(lo, hi);
+ return;
+ }
+ int mid = lo + diff / 2;
+ mergeSort(lo, mid);
+ mergeSort(mid, hi);
+ merge(lo, mid, hi, mid - lo, hi - mid);
+ }
+
+ private void merge(int lo, int pivot, int hi, int len1, int len2) {
+ if (len1 == 0 || len2 == 0) {
+ return;
+ }
+ if (len1 + len2 == 2) {
+ if (compare(pivot, lo) < 0) {
+ swap(pivot, lo);
+ }
+ return;
+ }
+ int first_cut, second_cut;
+ int len11, len22;
+ if (len1 > len2) {
+ len11 = len1 / 2;
+ first_cut = lo + len11;
+ second_cut = lower(pivot, hi, first_cut);
+ len22 = second_cut - pivot;
+ } else {
+ len22 = len2 / 2;
+ second_cut = pivot + len22;
+ first_cut = upper(lo, pivot, second_cut);
+ len11 = first_cut - lo;
+ }
+ rotate(first_cut, pivot, second_cut);
+ int new_mid = first_cut + len22;
+ merge(lo, first_cut, new_mid, len11, len22);
+ merge(new_mid, second_cut, hi, len1 - len11, len2 - len22);
+ }
+
+ private void rotate(int lo, int mid, int hi) {
+ int lot = lo;
+ int hit = mid - 1;
+ while (lot < hit) {
+ swap(lot++, hit--);
+ }
+ lot = mid; hit = hi - 1;
+ while (lot < hit) {
+ swap(lot++, hit--);
+ }
+ lot = lo; hit = hi - 1;
+ while (lot < hit) {
+ swap(lot++, hit--);
+ }
+ }
+
+ private int lower(int lo, int hi, int val) {
+ int len = hi - lo;
+ while (len > 0) {
+ int half = len / 2;
+ int mid= lo + half;
+ if (compare(mid, val) < 0) {
+ lo = mid + 1;
+ len = len - half -1;
+ } else {
+ len = half;
+ }
+ }
+ return lo;
+ }
+
+ private int upper(int lo, int hi, int val) {
+ int len = hi - lo;
+ while (len > 0) {
+ int half = len / 2;
+ int mid = lo + half;
+ if (compare(val, mid) < 0) {
+ len = half;
+ } else {
+ lo = mid + 1;
+ len = len - half -1;
+ }
+ }
+ return lo;
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/StringSwitcher.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/StringSwitcher.java
new file mode 100644
index 0000000..cd4123b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/cglib/util/StringSwitcher.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+package org.powermock.api.mockito.repackaged.cglib.util;
+
+import org.powermock.api.mockito.repackaged.asm.ClassVisitor;
+import org.powermock.api.mockito.repackaged.asm.Label;
+import org.powermock.api.mockito.repackaged.asm.Type;
+import org.powermock.api.mockito.repackaged.cglib.core.AbstractClassGenerator;
+import org.powermock.api.mockito.repackaged.cglib.core.ClassEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.CodeEmitter;
+import org.powermock.api.mockito.repackaged.cglib.core.Constants;
+import org.powermock.api.mockito.repackaged.cglib.core.EmitUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.KeyFactory;
+import org.powermock.api.mockito.repackaged.cglib.core.ObjectSwitchCallback;
+import org.powermock.api.mockito.repackaged.cglib.core.ReflectUtils;
+import org.powermock.api.mockito.repackaged.cglib.core.Signature;
+import org.powermock.api.mockito.repackaged.cglib.core.TypeUtils;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class implements a simple String->int mapping for a fixed set of keys.
+ */
+abstract public class StringSwitcher {
+ private static final Type STRING_SWITCHER =
+ TypeUtils.parseType("org.powermock.api.mockito.repackaged.cglib.util.StringSwitcher");
+ private static final Signature INT_VALUE =
+ TypeUtils.parseSignature("int intValue(String)");
+ private static final StringSwitcherKey KEY_FACTORY =
+ (StringSwitcherKey) KeyFactory.create(StringSwitcherKey.class);
+
+ protected StringSwitcher() {
+ }
+
+ /**
+ * Helper method to create a StringSwitcher.
+ * For finer control over the generated instance, use a new instance of StringSwitcher.Generator
+ * instead of this static method.
+ * @param strings the array of String keys; must be the same length as the value array
+ * @param ints the array of integer results; must be the same length as the key array
+ * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
+ * the result will be undefined, and the resulting code will be faster
+ */
+ public static StringSwitcher create(String[] strings, int[] ints, boolean fixedInput) {
+ Generator gen = new Generator();
+ gen.setStrings(strings);
+ gen.setInts(ints);
+ gen.setFixedInput(fixedInput);
+ return gen.create();
+ }
+
+ /**
+ * Return the integer associated with the given key.
+ * @param s the key
+ * @return the associated integer value, or <code>-1</code> if the key is unknown (unless
+ * <code>fixedInput</code> was specified when this <code>StringSwitcher</code> was created,
+ * in which case the return value for an unknown key is undefined)
+ */
+ abstract public int intValue(String s);
+
+ interface StringSwitcherKey {
+ public Object newInstance(String[] strings, int[] ints, boolean fixedInput);
+ }
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(StringSwitcher.class.getName());
+
+ private String[] strings;
+ private int[] ints;
+ private boolean fixedInput;
+
+ public Generator() {
+ super(SOURCE);
+ }
+
+ /**
+ * Set the array of recognized Strings.
+ * @param strings the array of String keys; must be the same length as the value array
+ * @see #setInts
+ */
+ public void setStrings(String[] strings) {
+ this.strings = strings;
+ }
+
+ /**
+ * Set the array of integer results.
+ * @param ints the array of integer results; must be the same length as the key array
+ * @see #setStrings
+ */
+ public void setInts(int[] ints) {
+ this.ints = ints;
+ }
+
+ /**
+ * Configure how unknown String keys will be handled.
+ * @param fixedInput if false, an unknown key will be returned from {@link #intValue} as <code>-1</code>; if true,
+ * the result will be undefined, and the resulting code will be faster
+ */
+ public void setFixedInput(boolean fixedInput) {
+ this.fixedInput = fixedInput;
+ }
+
+ protected ClassLoader getDefaultClassLoader() {
+ return getClass().getClassLoader();
+ }
+
+ /**
+ * Generate the <code>StringSwitcher</code>.
+ */
+ public StringSwitcher create() {
+ setNamePrefix(StringSwitcher.class.getName());
+ Object key = KEY_FACTORY.newInstance(strings, ints, fixedInput);
+ return (StringSwitcher)super.create(key);
+ }
+
+ public void generateClass(ClassVisitor v) throws Exception {
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ STRING_SWITCHER,
+ null,
+ Constants.SOURCE_FILE);
+ EmitUtils.null_constructor(ce);
+ final CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, INT_VALUE, null);
+ e.load_arg(0);
+ final List stringList = Arrays.asList(strings);
+ int style = fixedInput ? Constants.SWITCH_STYLE_HASHONLY : Constants.SWITCH_STYLE_HASH;
+ EmitUtils.string_switch(e, strings, style, new ObjectSwitchCallback() {
+ public void processCase(Object key, Label end) {
+ e.push(ints[stringList.indexOf(key)]);
+ e.return_value();
+ }
+ public void processDefault() {
+ e.push(-1);
+ e.return_value();
+ }
+ });
+ e.end_method();
+ ce.end_class();
+ }
+
+ protected Object firstInstance(Class type) {
+ return (StringSwitcher) ReflectUtils.newInstance(type);
+ }
+
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+ }
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package-info.java b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package-info.java
new file mode 100644
index 0000000..b9dc321
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package-info.java
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) 2007 Mockito contributors
+ * This program is made available under the terms of the MIT License.
+ */
+
+/**
+ * Mockito related CGLIB stuff. Repackaged from Mockito 2.0.43-beta with public visibility and cglib.
+ */
+package org.powermock.api.mockito.repackaged;
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package.html b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package.html
new file mode 100644
index 0000000..72e09a2
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/repackaged/package.html
@@ -0,0 +1,6 @@
+<!--
+ ~ Copyright (c) 2007 Mockito contributors
+ ~ This program is made available under the terms of the MIT License.
+ -->
+
+<body>CGLIB related stuff</body>
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java
new file mode 100644
index 0000000..952bea7
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/ConstructorArgumentsVerification.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.verification;
+
+public interface ConstructorArgumentsVerification {
+
+ void withArguments(Object argument, Object... additionalArguments) throws Exception;
+
+ void withNoArguments() throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java
new file mode 100644
index 0000000..d13d480
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/PrivateMethodVerification.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.verification;
+
+import java.lang.reflect.Method;
+
+public interface PrivateMethodVerification {
+
+ /**
+ * Verify calls to private methods without having to specify the method
+ * name. The method will be looked up using the parameter types (if
+ * possible).
+ *
+ * @throws Exception If something unexpected goes wrong.
+ */
+ public void invoke(Object... arguments) throws Exception;
+
+ /**
+ * Verify calls to the specific method.
+ *
+ * @throws Exception If something unexpected goes wrong.
+ */
+ public WithOrWithoutVerifiedArguments invoke(Method method) throws Exception;
+
+ /**
+ * Verify a private method call by specifying the method name of the method
+ * to verify.
+ *
+ * @throws Exception If something unexpected goes wrong.
+ * @see {@link #invoke(Object...)}
+ */
+ public void invoke(String methodToVerify, Object... arguments) throws Exception;
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java
new file mode 100644
index 0000000..65b34bd
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithOrWithoutVerifiedArguments.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.verification;
+
+public interface WithOrWithoutVerifiedArguments extends WithVerifiedArguments, WithoutVerifiedArguments {
+}
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java
new file mode 100644
index 0000000..900d56d
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithVerifiedArguments.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.verification;
+
+
+public interface WithVerifiedArguments {
+
+ public abstract void withArguments(Object firstArgument, Object... additionalArguments) throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java
new file mode 100644
index 0000000..b55ea5b
--- /dev/null
+++ b/api/mockito2/src/main/java/org/powermock/api/mockito/verification/WithoutVerifiedArguments.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.api.mockito.verification;
+
+public interface WithoutVerifiedArguments {
+
+ public void withNoArguments() throws Exception;
+
+}
\ No newline at end of file
diff --git a/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker b/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
new file mode 100644
index 0000000..0388d5c
--- /dev/null
+++ b/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.MockMaker
@@ -0,0 +1 @@
+org.powermock.api.mockito.internal.mockmaker.PowerMockMaker
\ No newline at end of file
diff --git a/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider b/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider
new file mode 100644
index 0000000..7f689ce
--- /dev/null
+++ b/api/mockito2/src/main/resources/mockito-extensions/org.mockito.plugins.StackTraceCleanerProvider
@@ -0,0 +1 @@
+org.powermock.api.mockito.internal.exceptions.StackTraceCleanerProvider
\ No newline at end of file
diff --git a/api/mockito2/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java
new file mode 100644
index 0000000..053831e
--- /dev/null
+++ b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/expectation/DefaultMethodExpectationSetupTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.mockito.internal.expectation;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.powermock.reflect.Whitebox;
+
+/**
+ * @author Stanislav Chizhov
+ */
+public class DefaultMethodExpectationSetupTest {
+
+ private final CUT object = new CUT();
+
+ @Test(expected = MissingMethodInvocationException.class)
+ public void testWithArguments_Multiple() throws Exception {
+ DefaultMethodExpectationSetup s = new DefaultMethodExpectationSetup(object, object.getClass().getMethod("multiple", Object.class, Object.class, Object.class));
+ Object a1 = new Object();
+ Object a2 = new Object();
+ Object a3 = new Object();
+ s.withArguments(a1, a2, a3);
+ }
+
+ @Test(expected = MissingMethodInvocationException.class)
+ public void testWithArguments_Single() throws Exception {
+ DefaultMethodExpectationSetup s = new DefaultMethodExpectationSetup(object, object.getClass().getMethod("single", Object.class));
+ Object a1 = new Object();
+ s.withArguments(a1);
+ }
+
+ @Test
+ public void testJoin() throws Exception {
+ Object a1 = new Object();
+ Object a2 = new Object();
+ Object a3 = new Object();
+ Object[] res = Whitebox.invokeMethod(DefaultMethodExpectationSetup.class, "join", a1, new Object[]{a2, a3});
+
+ Assert.assertArrayEquals(new Object[]{a1, a2, a3}, res);
+ }
+
+ public static class CUT {
+
+ public void multiple(Object a1, Object a2, Object a3) {
+ //Nada
+ }
+
+ public void single(Object a1) {
+ //Nada
+ }
+ }
+}
diff --git a/api/mockito2/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java
new file mode 100644
index 0000000..55be0cc
--- /dev/null
+++ b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/mockcreation/MockCreatorTest.java
@@ -0,0 +1,43 @@
+package org.powermock.api.mockito.internal.mockcreation;
+
+import org.junit.Test;
+import org.mockito.internal.creation.MockSettingsImpl;
+import org.mockito.internal.util.MockUtil;
+import org.mockito.mock.MockName;
+
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class MockCreatorTest {
+
+ private final MockUtil util = new MockUtil();
+
+ @Test
+ public void testMock_shouldReturnMockNameWhenSettingsHaveName()
+ throws NoSuchMethodException, SecurityException {
+ final MockSettingsImpl<List<?>> settings = new MockSettingsImpl<List<?>>();
+ settings.name("mylist");
+
+ final List<?> result = MockCreator.mock(List.class, false, false, null,
+ settings, List.class.getMethod("add", Object.class));
+
+ final MockName mockName = util.getMockName(result);
+ assertNotNull(mockName);
+ assertEquals("mylist", mockName.toString());
+ }
+
+ @Test
+ public void testMock_shouldReturnClassNameWhenSettingsHaveNoName()
+ throws NoSuchMethodException, SecurityException {
+ final MockSettingsImpl<List<?>> settings = new MockSettingsImpl<List<?>>();
+
+ final List<?> result = MockCreator.mock(List.class, false, false, null,
+ settings, List.class.getMethod("add", Object.class));
+
+ final MockName mockName = util.getMockName(result);
+ assertNotNull(mockName);
+ assertEquals("list", mockName.toString());
+ }
+}
diff --git a/api/mockito2/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java
new file mode 100644
index 0000000..feba476
--- /dev/null
+++ b/api/mockito2/src/test/java/org/powermock/api/mockito/internal/stubbing/answers/ChainReturnsTest.java
@@ -0,0 +1,54 @@
+package org.powermock.api.mockito.internal.stubbing.answers;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+/**
+ * Created by gauee on 12/11/15.
+ */
+public class ChainReturnsTest {
+
+ public static final String ANSWER_FIRST = "answerFirst";
+ public static final String ANSWER_SECOND = "answerSecond";
+ private InvocationOnMock invocationOnMock;
+
+ @Before
+ public void init() {
+ this.invocationOnMock = mock(InvocationOnMock.class);
+ }
+
+
+ @Test
+ public void returnsTwoDifferentAnswers() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, ANSWER_SECOND);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_FIRST)));
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_SECOND)));
+ }
+
+ @Test
+ public void returnsFirstAnswerAndNullValue() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, null);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_FIRST)));
+ assertThat(chainReturns.answer(invocationOnMock), is(nullValue()));
+ }
+
+ @Test
+ public void returnsAlwaysLastDeclaredAnswer() throws Throwable {
+ ChainReturns chainReturns = new ChainReturns(ANSWER_FIRST, ANSWER_SECOND);
+
+ chainReturns.answer(invocationOnMock);
+ chainReturns.answer(invocationOnMock);
+
+ assertThat((String) chainReturns.answer(invocationOnMock), is(equalTo(ANSWER_SECOND)));
+ }
+
+}
\ No newline at end of file
diff --git a/api/pom.xml b/api/pom.xml
new file mode 100644
index 0000000..6aac386
--- /dev/null
+++ b/api/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-api</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ The mocking framework-specific interfaces to PowerMock.
+ </description>
+
+ <modules>
+ <module>easymock</module>
+ <module>support</module>
+ <module>mockito-common</module>
+ <module>mockito</module>
+ <module>mockito2</module>
+ </modules>
+</project>
diff --git a/api/support/pom.xml b/api/support/pom.xml
new file mode 100644
index 0000000..0f21323
--- /dev/null
+++ b/api/support/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-api-support</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Utility classes.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/api/support/src/main/java/org/powermock/api/extension/reporter/AbstractMockingFrameworkReporterFactory.java b/api/support/src/main/java/org/powermock/api/extension/reporter/AbstractMockingFrameworkReporterFactory.java
new file mode 100644
index 0000000..1f3f1c6
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/extension/reporter/AbstractMockingFrameworkReporterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.api.extension.reporter;
+
+import org.powermock.core.reporter.MockingFrameworkReporter;
+import org.powermock.core.reporter.MockingFrameworkReporterFactory;
+import org.powermock.reflect.Whitebox;
+
+/**
+ * Abstract implementation of the {@link MockingFrameworkReporterFactory}, contains common code for EasyMock and
+ * Mockito.
+ */
+ at SuppressWarnings("WeakerAccess")
+public abstract class AbstractMockingFrameworkReporterFactory implements MockingFrameworkReporterFactory {
+ @Override
+ public MockingFrameworkReporter create() {
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ return getInstanceForClassLoader(classLoader);
+
+ }
+
+ private MockingFrameworkReporter getInstanceForClassLoader(ClassLoader classLoader) {
+ Class<MockingFrameworkReporter> frameworkReporterClass = getMockingFrameworkReporterClass(classLoader);
+ return Whitebox.newInstance(frameworkReporterClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ private Class<MockingFrameworkReporter> getMockingFrameworkReporterClass(ClassLoader classLoader) {
+ Class<MockingFrameworkReporter> frameworkReporterClass;
+ try {
+ frameworkReporterClass = (Class<MockingFrameworkReporter>) classLoader.loadClass(getImplementerClassName());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return frameworkReporterClass;
+ }
+
+ protected abstract String getImplementerClassName();
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/ClassLoaderUtil.java b/api/support/src/main/java/org/powermock/api/support/ClassLoaderUtil.java
new file mode 100644
index 0000000..4098553
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/ClassLoaderUtil.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support;
+
+public class ClassLoaderUtil {
+
+ /**
+ * Loads a class with a specific classloader, wraps the
+ * {@link ClassNotFoundException} in a runtime exeception.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Class<T> loadClass(Class<T> type, ClassLoader classloader) {
+ return loadClass(type.getName(), classloader);
+ }
+
+ /**
+ * Loads a class from the current classloader
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Class<T> loadClass(String className) {
+ return loadClass(className, ClassLoaderUtil.class.getClassLoader());
+ }
+
+ /**
+ * Check whether a classloader can load the given class.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> boolean hasClass(Class<T> type, ClassLoader classloader) {
+ try {
+ loadClass(type.getName(), classloader);
+ return true;
+ } catch (RuntimeException e) {
+ if(e.getCause() instanceof ClassNotFoundException) {
+ return false;
+ }
+ throw e;
+ }
+ }
+
+ /**
+ * Load a class from a specific classloader
+ */
+ public static <T> Class<T> loadClass(String className, ClassLoader classloader) {
+ if(className == null) {
+ throw new IllegalArgumentException("className cannot be null");
+ }
+
+ if(classloader == null) {
+ throw new IllegalArgumentException("classloader cannot be null");
+ }
+
+ try {
+ return (Class<T>) Class.forName(className, false, classloader);
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/MethodProxy.java b/api/support/src/main/java/org/powermock/api/support/MethodProxy.java
new file mode 100644
index 0000000..b396c1f
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/MethodProxy.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support;
+
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class MethodProxy {
+ /**
+ * Add a proxy for this method. Each call to the method will be routed to
+ * the invocationHandler instead.
+ */
+ public static void proxy(Method method, InvocationHandler invocationHandler) {
+ assertInvocationHandlerNotNull(invocationHandler);
+ MockRepository.putMethodProxy(method, invocationHandler);
+ }
+
+ /**
+ * Add a proxy for a method declared in class <code>declaringClass</code>.
+ * Each call to the method will be routed to the invocationHandler instead.
+ */
+ public static void proxy(Class<?> declaringClass, String methodName, InvocationHandler invocationHandler) {
+ assertInvocationHandlerNotNull(invocationHandler);
+ if (declaringClass == null) {
+ throw new IllegalArgumentException("declaringClass cannot be null");
+ }
+ if (methodName == null || methodName.length() == 0) {
+ throw new IllegalArgumentException("methodName cannot be empty");
+ }
+ Method[] methods = Whitebox.getMethods(declaringClass, methodName);
+ if (methods.length == 0) {
+ throw new MethodNotFoundException(String.format("Couldn't find a method with name %s in the class hierarchy of %s", methodName,
+ declaringClass.getName()));
+ } else if (methods.length > 1) {
+ throw new TooManyMethodsFoundException(String.format("Found %d methods with name %s in the class hierarchy of %s.", methods.length,
+ methodName, declaringClass.getName()));
+ }
+
+ MockRepository.putMethodProxy(methods[0], invocationHandler);
+ }
+
+ private static void assertInvocationHandlerNotNull(InvocationHandler invocationHandler) {
+ if (invocationHandler == null) {
+ throw new IllegalArgumentException("invocationHandler cannot be null");
+ }
+ }
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/SafeExceptionRethrower.java b/api/support/src/main/java/org/powermock/api/support/SafeExceptionRethrower.java
new file mode 100644
index 0000000..4652d68
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/SafeExceptionRethrower.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support;
+
+public class SafeExceptionRethrower {
+
+ public static void safeRethrow(Throwable t) {
+ SafeExceptionRethrower.<RuntimeException> safeRethrow0(t);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void safeRethrow0(Throwable t) throws T {
+ throw (T) t;
+ }
+
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/Stubber.java b/api/support/src/main/java/org/powermock/api/support/Stubber.java
new file mode 100644
index 0000000..44e6b53
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/Stubber.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support;
+
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+
+import java.lang.reflect.Method;
+
+public class Stubber {
+ /**
+ * Add a method that should be intercepted and return another value (
+ * <code>returnObject</code>) (i.e. the method is stubbed).
+ */
+ public static void stubMethod(Method method, Object returnObject) {
+ MockRepository.putMethodToStub(method, returnObject);
+ }
+
+ /**
+ * Add a method that should be intercepted and return another value (
+ * <code>returnObject</code>) (i.e. the method is stubbed).
+ */
+ public static void stubMethod(Class<?> declaringClass, String methodName, Object returnObject) {
+ if (declaringClass == null) {
+ throw new IllegalArgumentException("declaringClass cannot be null");
+ }
+ if (methodName == null || methodName.length() == 0) {
+ throw new IllegalArgumentException("methodName cannot be empty");
+ }
+ Method[] methods = Whitebox.getMethods(declaringClass, methodName);
+ if (methods.length == 0) {
+ throw new MethodNotFoundException(String.format("Couldn't find a method with name %s in the class hierarchy of %s", methodName,
+ declaringClass.getName()));
+ } else if (methods.length > 1) {
+ throw new TooManyMethodsFoundException(String.format("Found %d methods with name %s in the class hierarchy of %s.", methods.length,
+ methodName, declaringClass.getName()));
+ }
+
+ MockRepository.putMethodToStub(methods[0], returnObject);
+ }
+
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/SuppressCode.java b/api/support/src/main/java/org/powermock/api/support/SuppressCode.java
new file mode 100644
index 0000000..dac928d
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/SuppressCode.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support;
+
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+public class SuppressCode {
+ /**
+ * Suppress constructor calls on specific constructors only.
+ */
+ public static synchronized void suppressConstructor(Constructor<?>... constructors) {
+ if (constructors == null) {
+ throw new IllegalArgumentException("constructors cannot be null.");
+ }
+ for (Constructor<?> constructor : constructors) {
+ MockRepository.addConstructorToSuppress(constructor);
+ // Also suppress all parent constructors
+ Class<?> declaringClass = constructor.getDeclaringClass();
+ if (declaringClass != null) {
+ suppressConstructor((Class<?>) declaringClass.getSuperclass());
+ }
+ }
+ }
+
+ /**
+ * This method can be used to suppress the code in a specific constructor.
+ *
+ * @param clazz
+ * The class where the constructor is located.
+ * @param parameterTypes
+ * The parameter types of the constructor to suppress.
+ */
+ public static synchronized void suppressSpecificConstructor(Class<?> clazz, Class<?>... parameterTypes) {
+ MockRepository.addConstructorToSuppress(Whitebox.getConstructor(clazz, parameterTypes));
+ }
+
+ /**
+ * Suppress all constructors in the given class and it's super classes.
+ *
+ * @param classes
+ * The classes whose constructors will be suppressed.
+ */
+ public static synchronized void suppressConstructor(Class<?>... classes) {
+ for (Class<?> clazz : classes) {
+ Class<?> tempClass = clazz;
+ while (tempClass != Object.class) {
+ suppressConstructor(tempClass, false);
+ tempClass = tempClass.getSuperclass();
+ }
+ }
+ }
+
+ /**
+ * Suppress all constructors in the given class.
+ *
+ * @param classes
+ * The classes whose constructors will be suppressed.
+ * @param excludePrivateConstructors
+ * optionally keep code in private constructors
+ */
+ public static synchronized void suppressConstructor(Class<?> clazz, boolean excludePrivateConstructors) {
+ Constructor<?>[] ctors = null;
+
+ if (excludePrivateConstructors) {
+ ctors = clazz.getConstructors();
+ } else {
+ ctors = clazz.getDeclaredConstructors();
+ }
+
+ for (Constructor<?> ctor : ctors) {
+ MockRepository.addConstructorToSuppress(ctor);
+ }
+ }
+
+ /**
+ * Suppress specific fields. This works on both instance methods and static
+ * methods. Note that replay and verify are not needed as this is not part
+ * of a mock behavior.
+ */
+ public static synchronized void suppressField(Field... fields) {
+ for (Field field : fields) {
+ MockRepository.addFieldToSuppress(field);
+ }
+ }
+
+ /**
+ * Suppress all fields for these classes.
+ */
+ public static synchronized void suppressField(Class<?>[] classes) {
+ if (classes == null || classes.length == 0) {
+ throw new IllegalArgumentException("You must supply at least one class.");
+ }
+ for (Class<?> clazz : classes) {
+ suppressField(clazz.getDeclaredFields());
+ }
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param classes
+ * The class whose methods will be suppressed.
+ * @param fieldNames
+ * The names of the methods that'll be suppressed. If field names
+ * are empty, <i>all</i> fields in the supplied class will be
+ * suppressed.
+ */
+ public static synchronized void suppressField(Class<?> clazz, String... fieldNames) {
+ if (fieldNames == null || fieldNames.length == 0) {
+ suppressField(new Class<?>[] { clazz });
+ } else {
+ for (Field field : Whitebox.getFields(clazz, fieldNames)) {
+ MockRepository.addFieldToSuppress(field);
+ }
+ }
+ }
+
+ /**
+ * Suppress specific method calls on all types containing this method. This
+ * works on both instance methods and static methods. Note that replay and
+ * verify are not needed as this is not part of a mock behavior.
+ */
+ public static synchronized void suppressMethod(Method... methods) {
+ for (Method method : methods) {
+ MockRepository.addMethodToSuppress(method);
+ }
+ }
+
+ /**
+ * Suppress all methods for these classes.
+ *
+ * @param cls
+ * The first class whose methods will be suppressed.
+ * @param additionalClasses
+ * Additional classes whose methods will be suppressed.
+ */
+ public static synchronized void suppressMethod(Class<?> cls, Class<?>... additionalClasses) {
+ suppressMethod(cls, false);
+ for (Class<?> clazz : additionalClasses) {
+ suppressMethod(clazz, false);
+ }
+ }
+
+ /**
+ * Suppress all methods for these classes.
+ *
+ * @param classes
+ * Classes whose methods will be suppressed.
+ */
+ public static synchronized void suppressMethod(Class<?>[] classes) {
+ for (Class<?> clazz : classes) {
+ suppressMethod(clazz, false);
+ }
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param clazz
+ * The class whose methods will be suppressed.
+ * @param methodName
+ * The first method to be suppress in class <code>clazz</code>.
+ * @param additionalMethodNames
+ * Additional methods to suppress in class <code>clazz</code>.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String methodName, String... additionalMethodNames) {
+ for (Method method : Whitebox.getMethods(clazz, methodName)) {
+ MockRepository.addMethodToSuppress(method);
+ }
+ if (additionalMethodNames != null && additionalMethodNames.length > 0) {
+ for (Method method : Whitebox.getMethods(clazz, additionalMethodNames)) {
+ MockRepository.addMethodToSuppress(method);
+ }
+ }
+ }
+
+ /**
+ * Suppress multiple methods for a class.
+ *
+ * @param clazz
+ * The class whose methods will be suppressed.
+ * @param methodNames
+ * Methods to suppress in class <code>clazz</code>.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String[] methodNames) {
+ for (Method method : Whitebox.getMethods(clazz, methodNames)) {
+ MockRepository.addMethodToSuppress(method);
+ }
+ }
+
+ /**
+ * suSuppress all methods for this class.
+ *
+ * @param classes
+ * The class which methods will be suppressed.
+ * @param excludePrivateMethods
+ * optionally not suppress private methods
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, boolean excludePrivateMethods) {
+ Method[] methods = null;
+
+ if (excludePrivateMethods) {
+ methods = clazz.getMethods();
+ } else {
+ methods = clazz.getDeclaredMethods();
+ }
+
+ for (Method method : methods) {
+ MockRepository.addMethodToSuppress(method);
+ }
+ }
+
+ /**
+ * Suppress a specific method call. Use this for overloaded methods.
+ */
+ public static synchronized void suppressMethod(Class<?> clazz, String methodName, Class<?>[] parameterTypes) {
+ Method method = null;
+ if (parameterTypes.length > 0) {
+ method = Whitebox.getMethod(clazz, methodName, parameterTypes);
+ } else {
+ method = WhiteboxImpl.findMethodOrThrowException(clazz, methodName, parameterTypes);
+ }
+ MockRepository.addMethodToSuppress(method);
+ }
+
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/MemberMatcher.java b/api/support/src/main/java/org/powermock/api/support/membermodification/MemberMatcher.java
new file mode 100644
index 0000000..fa78652
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/MemberMatcher.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification;
+
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.*;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.tests.utils.impl.ArrayMergerImpl;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+/**
+ * Finds members in classes.
+ */
+public class MemberMatcher {
+
+ /**
+ * Get all methods in a class hierarchy of the supplied classes. Both
+ * declared an non-declared (no duplicates).
+ *
+ * @param cls
+ * The class whose methods to get.
+ * @param additionalClasses
+ * Additional classes whose methods to get.
+ * @return All methods declared in this class hierarchy.
+ */
+ public static Method[] methodsDeclaredIn(final Class<?> cls, final Class<?>... additionalClasses) {
+ if (cls == null) {
+ throw new IllegalArgumentException("You need to supply at least one class.");
+ }
+ Set<Method> methods = new HashSet<Method>();
+ methods.addAll(asList(WhiteboxImpl.getAllMethods(cls)));
+ for (Class<?> klass : additionalClasses) {
+ methods.addAll(asList(WhiteboxImpl.getAllMethods(klass)));
+ }
+ return methods.toArray(new Method[methods.size()]);
+ }
+
+ /**
+ * Get a method when it cannot be determined by methodName or parameter
+ * types only.
+ * <p>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link IllegalArgumentException}
+ * is thrown.
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the method is located.
+ * @param methodName
+ * The method names.
+ * @param parameterTypes
+ * All parameter types of the method (may be <code>null</code>).
+ * @return A <code>java.lang.reflect.Method</code>.
+ * @throws MethodNotFoundException
+ * If a method cannot be found in the hierarchy.
+ */
+ public static Method method(Class<?> declaringClass, String methodName, Class<?>... parameterTypes) {
+ final Method method = WhiteboxImpl.findMethod(declaringClass, methodName, parameterTypes);
+ WhiteboxImpl.throwExceptionIfMethodWasNotFound(declaringClass, methodName, method, (Object[]) parameterTypes);
+ return method;
+ }
+
+ /**
+ * Get a method without having to specify the method name.
+ * <p>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link IllegalArgumentException}
+ * is thrown. Since the method name is not specified an
+ * {@link IllegalArgumentException} is thrown if two or more methods matches
+ * the same parameter types in the same class.
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the method is located.
+ * @param parameterTypes
+ * All parameter types of the method (may be <code>null</code>).
+ * @return A <code>java.lang.reflect.Method</code>.
+ * @throws MethodNotFoundException
+ * If a method cannot be found in the hierarchy.
+ * @throws TooManyMethodsFoundException
+ * If several methods were found.
+ */
+ public static Method method(Class<?> declaringClass, Class<?>... parameterTypes) {
+ return Whitebox.getMethod(declaringClass, parameterTypes);
+ }
+
+ /**
+ * Get an array of {@link Method}'s that matches the supplied list of method
+ * names. Both instance and static methods are taken into account.
+ *
+ * @param clazz
+ * The class that should contain the methods.
+ * @param methodName
+ * The name of the first method.
+ * @param additionalMethodNames
+ * Additional names of the methods that will be returned.
+ * @return An array of Method's. May be of length 0 but not
+ * <code>null</code>.
+ * @throws MethodNotFoundException
+ * If no method was found.
+ */
+ public static Method[] methods(Class<?> clazz, String methodName, String... additionalMethodNames) {
+ return Whitebox.getMethods(clazz, merge(methodName, additionalMethodNames));
+ }
+
+ /**
+ * Get an array of {@link Field}'s.
+ *
+ * @param method
+ * The first field.
+ * @param additionalMethods
+ * Additional fields
+ * @return An array of {@link Field}.
+ */
+ public static Method[] methods(Method method, Method... additionalMethods) {
+ return merge(method, additionalMethods);
+ }
+
+ /**
+ * Get an array of {@link Method}'s that matches the supplied list of method
+ * names. Both instance and static methods are taken into account.
+ *
+ * @param clazz
+ * The class that should contain the methods.
+ * @param methodNames
+ * The names of the methods.
+ * @return An array of Method's. May be of length 0 but not
+ * <code>null</code>.
+ * @throws MethodNotFoundException
+ * If no method was found.
+ */
+ public static Method[] methods(Class<?> clazz, String[] methodNames) {
+ return Whitebox.getMethods(clazz, methodNames);
+ }
+
+ /**
+ * Get a field from a class.
+ * <p>
+ * The method will first try to look for a declared field in the same class.
+ * If the method is not declared in this class it will look for the field in
+ * the super class. This will continue throughout the whole class hierarchy.
+ * If the field is not found an {@link IllegalArgumentException} is thrown.
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the method is located.
+ * @param fieldName
+ * The method names.
+ * @return A <code>java.lang.reflect.Field</code>.
+ * @throws FieldNotFoundException
+ * If a field cannot be found in the hierarchy.
+ */
+ public static Field field(Class<?> declaringClass, String fieldName) {
+ return Whitebox.getField(declaringClass, fieldName);
+ }
+
+ /**
+ * Get an array of {@link Field}'s that matches the supplied list of field
+ * names.
+ *
+ * @param clazz
+ * The class that should contain the fields.
+ * @param firstFieldName
+ * The name of the first field.
+ * @param additionalfieldNames
+ * The additional names of the fields that will be returned.
+ * @return An array of Field's. May be of length 0 but not <code>null</code>
+ *
+ */
+ public static Field[] fields(Class<?> clazz, String firstFieldName, String... additionalfieldNames) {
+ return Whitebox.getFields(clazz, merge(firstFieldName, additionalfieldNames));
+ }
+
+ /**
+ * Get all fields in a class hierarchy.
+ *
+ * @param clazz
+ * The class that should contain the fields.
+ * @param firstFieldName
+ * The name of the first field.
+ * @param additionalfieldNames
+ * The additional names of the fields that will be returned.
+ * @return An array of Field's. May be of length 0 but not <code>null</code>
+ *
+ */
+ public static Field[] fields(Class<?> clazz) {
+ return WhiteboxImpl.getAllFields(clazz);
+ }
+
+ /**
+ * Get an array of {@link Field}'s.
+ *
+ * @param field
+ * The first field.
+ * @param additionalFields
+ * Additional fields
+ * @return An array of {@link Field}.
+ */
+ public static Field[] fields(Field field, Field... additionalFields) {
+ return merge(field, additionalFields);
+ }
+
+ /**
+ * Get an array of {@link Field}'s that matches the supplied list of field
+ * names.
+ *
+ * @param clazz
+ * The class that should contain the fields.
+ * @param fieldNames
+ * The names of the fields that will be returned.
+ * @return An array of Field's. May be of length 0 but not <code>null</code>
+ *
+ */
+ public static Field[] fields(Class<?> clazz, String[] fieldNames) {
+ return Whitebox.getFields(clazz, fieldNames);
+ }
+
+ /**
+ * Returns a constructor specified in declaringClass.
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the constructor is
+ * located.
+ * @param parameterTypes
+ * All parameter types of the constructor (may be
+ * <code>null</code>).
+ * @return A <code>java.lang.reflect.Constructor</code>.
+ * @throws ConstructorNotFoundException
+ * if the constructor cannot be found.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Constructor<T> constructor(Class<T> declaringClass, Class<?>... parameterTypes) {
+ return (Constructor<T>) WhiteboxImpl.findUniqueConstructorOrThrowException(declaringClass,
+ (Object[]) parameterTypes);
+ }
+
+ /**
+ * Returns any one constructor specified in declaringClass. Is is useful when you only have ONE constructor
+ * declared in <code>declaringClass</code> but you don't care which parameters it take.
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the constructor is
+ * located.
+ * @return A <code>java.lang.reflect.Constructor</code>.
+ * @throws TooManyConstructorsFoundException
+ * If more than one constructor was present in
+ * <code>declaringClass</code>
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Constructor<T> constructor(Class<T> declaringClass) {
+ return (Constructor<T>) WhiteboxImpl.findConstructorOrThrowException(declaringClass);
+ }
+
+ /**
+ * Returns the default constructor in <code>declaringClass</code>
+ *
+ * @param declaringClass
+ * The declaringClass of the class where the constructor is
+ * located.
+ * @return A <code>java.lang.reflect.Constructor</code>.
+ * @throws ConstructorNotFoundException
+ * If no default constructor was found in <code>declaringClass</code>
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Constructor<T> defaultConstructorIn(Class<T> declaringClass) {
+ return (Constructor<T>) WhiteboxImpl.findDefaultConstructorOrThrowException(declaringClass);
+ }
+
+ /**
+ * Get all constructors in the supplied class(es).
+ *
+ * @param cls
+ * The class whose constructors to get.
+ * @param additionalClasses
+ * Additional classes whose constructors to get.
+ * @return All constructors declared in this class.
+ */
+ public static Constructor<?>[] constructorsDeclaredIn(final Class<?> cls, final Class<?>... additionalClasses) {
+ if (cls == null) {
+ throw new IllegalArgumentException("You need to supply at least one class.");
+ }
+ Set<Constructor<?>> constructors = new HashSet<Constructor<?>>();
+ constructors.addAll(asList(WhiteboxImpl.getAllConstructors(cls)));
+ for (Class<?> klass : additionalClasses) {
+ constructors.addAll(asList(WhiteboxImpl.getAllConstructors(klass)));
+ }
+ return constructors.toArray(new Constructor[constructors.size()]);
+ }
+
+ /**
+ * Convenience method to get a constructor from a class.
+ *
+ * @param constructor
+ * The first constructor.
+ * @param additionalConstructors
+ * Additional constructors
+ * @return An array of <code>java.lang.reflect.Constructor</code>.
+ */
+ public static Constructor<?>[] constructors(Constructor<?> constructor, Constructor<?>... additionalConstructors) {
+ return merge(constructor, additionalConstructors);
+ }
+
+ /**
+ * Get all constructors and methods in the supplied class(es).
+ *
+ * @param cls
+ * The class whose constructors and methods to get.
+ * @param additionalClasses
+ * Additional classes whose constructors and methods to get.
+ * @return All constructors and methods declared in this class.
+ */
+ public static AccessibleObject[] everythingDeclaredIn(final Class<?> cls, final Class<?>... additionalClasses) {
+ if (cls == null) {
+ throw new IllegalArgumentException("You need to supply at least one class.");
+ }
+ Set<AccessibleObject> accessibleObjects = new HashSet<AccessibleObject>();
+ accessibleObjects.addAll(Collections.unmodifiableCollection(asList(methodsDeclaredIn(cls, additionalClasses))));
+ accessibleObjects.addAll(Collections.unmodifiableCollection(asList(constructorsDeclaredIn(cls,
+ additionalClasses))));
+ return accessibleObjects.toArray(new AccessibleObject[accessibleObjects.size()]);
+ }
+
+ private static String[] merge(String first, String... additional) {
+ return new ArrayMergerImpl().mergeArrays(String.class, new String[] { first }, additional);
+ }
+
+ private static Method[] merge(Method first, Method... additional) {
+ return new ArrayMergerImpl().mergeArrays(Method.class, new Method[] { first }, additional);
+ }
+
+ private static Field[] merge(Field first, Field... additional) {
+ return new ArrayMergerImpl().mergeArrays(Field.class, new Field[] { first }, additional);
+ }
+
+ private static Constructor<?>[] merge(Constructor<?> first, Constructor<?>... additional) {
+ return new ArrayMergerImpl().mergeArrays(Constructor.class, new Constructor<?>[] { first }, additional);
+ }
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/MemberModifier.java b/api/support/src/main/java/org/powermock/api/support/membermodification/MemberModifier.java
new file mode 100644
index 0000000..42c9bc7
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/MemberModifier.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.api.support.membermodification;
+
+import org.powermock.api.support.SuppressCode;
+import org.powermock.api.support.membermodification.strategy.MethodReplaceStrategy;
+import org.powermock.api.support.membermodification.strategy.MethodStubStrategy;
+import org.powermock.api.support.membermodification.strategy.impl.MethodReplaceStrategyImpl;
+import org.powermock.api.support.membermodification.strategy.impl.MethodStubStrategyImpl;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * Contains various utilities for modifying members of classes such as
+ * constructors, fields and methods. Modifying means e.g. changing return value
+ * of method invocations or suppressing a constructor.
+ */
+public class MemberModifier extends MemberMatcher {
+
+ /**
+ * Suppress a specific method. This works on both instance methods and
+ * static methods.
+ */
+ public static void suppress(Method method) {
+ SuppressCode.suppressMethod(method);
+ }
+
+ /**
+ * Suppress multiple methods. This works on both instance methods and static
+ * methods.
+ */
+ public static void suppress(Method[] methods) {
+ SuppressCode.suppressMethod(methods);
+ }
+
+ /**
+ * Suppress a constructor.
+ */
+ public static void suppress(Constructor<?> constructor) {
+ SuppressCode.suppressConstructor(constructor);
+ }
+
+ /**
+ * Suppress multiple constructors.
+ */
+ public static void suppress(Constructor<?>[] constructors) {
+ SuppressCode.suppressConstructor(constructors);
+ }
+
+ /**
+ * Suppress a field.
+ */
+ public static void suppress(Field field) {
+ SuppressCode.suppressField(field);
+ }
+
+ /**
+ * Suppress multiple fields.
+ */
+ public static void suppress(Field[] fields) {
+ SuppressCode.suppressField(fields);
+ }
+
+ /**
+ * Suppress an array of accessible objects.
+ */
+ public static void suppress(AccessibleObject[] accessibleObjects) {
+ if (accessibleObjects == null) {
+ throw new IllegalArgumentException("accessibleObjects cannot be null");
+ }
+
+ for (AccessibleObject accessibleObject : accessibleObjects) {
+ if (accessibleObject instanceof Constructor<?>) {
+ SuppressCode.suppressConstructor((Constructor<?>) accessibleObject);
+ } else if (accessibleObject instanceof Field) {
+ SuppressCode.suppressField((Field) accessibleObject);
+ } else if (accessibleObject instanceof Method) {
+ SuppressCode.suppressMethod((Method) accessibleObject);
+ }
+ }
+ }
+
+ /**
+ * Add a method that should be intercepted and return another value (i.e.
+ * the method is stubbed).
+ */
+ public static <T> MethodStubStrategy<T> stub(Method method) {
+ return new MethodStubStrategyImpl<T>(method);
+ }
+
+ /**
+ * Replace a method invocation.
+ */
+ public static MethodReplaceStrategy replace(Method method) {
+ return new MethodReplaceStrategyImpl(method);
+ }
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/ClassReplaceStrategy.java b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/ClassReplaceStrategy.java
new file mode 100644
index 0000000..d1704b0
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/ClassReplaceStrategy.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification.strategy;
+
+/**
+ * Specifies the replace strategy for a class.
+ */
+public interface ClassReplaceStrategy {
+
+ /**
+ * Replaces all method invocations on class specified class with method
+ * invocation to <code>cls</code>. Also replaces all constructor
+ * invocations. You can see this as duck typing.
+ *
+ * @param cls
+ * The class that will replace the other class.
+ */
+ void with(Class<?> cls);
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodReplaceStrategy.java b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodReplaceStrategy.java
new file mode 100644
index 0000000..1a101ac
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodReplaceStrategy.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification.strategy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Specifies the replace strategy for a method.
+ */
+public interface MethodReplaceStrategy {
+
+ /**
+ * Replaces the method invocation with this method.
+ * <p>
+ * Note that both methods needs to be static.
+ *
+ * @param method
+ * The method call will be replaced by this method instead. Needs
+ * to be static.
+ */
+ void with(Method method);
+
+ /**
+ * Replaces the method invocation with an invocation handler
+ *
+ * @param invocationHandler
+ * The invocation handler to replace the method call with.
+ */
+ void with(InvocationHandler invocationHandler);
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodStubStrategy.java b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodStubStrategy.java
new file mode 100644
index 0000000..f6869d5
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/MethodStubStrategy.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification.strategy;
+
+/**
+ * Specifies the return value when stubbing a method.
+ */
+public interface MethodStubStrategy<T> {
+
+ /**
+ * Stubs the method to return the specified returnValue.
+ *
+ * @param returnValue
+ * The value that will be returned.
+ * @deprecated Since version 1.4.1, use {@link #toReturn(Object)} instead.
+ */
+ void andReturn(T returnValue);
+
+ /**
+ * Stubs the method to return the specified returnValue.
+ *
+ * @param returnValue
+ * The value that will be returned.
+ */
+ void toReturn(T returnValue);
+
+ /**
+ * Stubs the method to throw the specified throwable.
+ *
+ * @param throwable
+ * the throwable
+ */
+ void toThrow(Throwable throwable);
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodReplaceStrategyImpl.java b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodReplaceStrategyImpl.java
new file mode 100644
index 0000000..3be60dd
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodReplaceStrategyImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification.strategy.impl;
+
+import org.powermock.api.support.MethodProxy;
+import org.powermock.api.support.membermodification.strategy.MethodReplaceStrategy;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+public class MethodReplaceStrategyImpl implements MethodReplaceStrategy {
+
+ private final Method method;
+
+ public MethodReplaceStrategyImpl(Method method) {
+ if (method == null) {
+ throw new IllegalArgumentException("Cannot replace a null method.");
+ }
+ this.method = method;
+ }
+
+ @Override
+ public void with(Method method) {
+ if (method == null) {
+ throw new IllegalArgumentException("A metod cannot be replaced with null.");
+ }
+ if (!Modifier.isStatic(this.method.getModifiers())) {
+ throw new IllegalArgumentException(String.format("Replace requires static methods, '%s' is not static", this.method));
+ } else if (!Modifier.isStatic(method.getModifiers())) {
+ throw new IllegalArgumentException(String.format("Replace requires static methods, '%s' is not static", method));
+ } else if(!this.method.getReturnType().isAssignableFrom(method.getReturnType())) {
+ throw new IllegalArgumentException(String.format("The replacing method (%s) needs to return %s and not %s.",method.toString(), this.method.getReturnType().getName(), method.getReturnType().getName()));
+ } else if(!WhiteboxImpl.checkIfParameterTypesAreSame(this.method.isVarArgs(),this.method.getParameterTypes(), method.getParameterTypes())) {
+ throw new IllegalArgumentException(String.format("The replacing method, \"%s\", needs to have the same number of parameters of the same type as as method \"%s\".",method.toString(),this.method.toString()));
+ } else {
+ MethodProxy.proxy(this.method, new MethodInvocationHandler(method));
+ }
+ }
+
+ @Override
+ public void with(InvocationHandler invocationHandler) {
+ if (invocationHandler == null) {
+ throw new IllegalArgumentException("Invocation handler cannot be null");
+ }
+ MethodProxy.proxy(method, invocationHandler);
+ }
+
+ private final class MethodInvocationHandler implements InvocationHandler {
+ private final Method methodDelegator;
+
+ public MethodInvocationHandler(Method methodDelegator) {
+ this.methodDelegator = methodDelegator;
+ }
+
+ @Override
+ public Object invoke(Object object, Method invokingMethod, Object[] arguments) throws Throwable {
+ return methodDelegator.invoke(object, arguments);
+ }
+ }
+}
diff --git a/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodStubStrategyImpl.java b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodStubStrategyImpl.java
new file mode 100644
index 0000000..3f413c4
--- /dev/null
+++ b/api/support/src/main/java/org/powermock/api/support/membermodification/strategy/impl/MethodStubStrategyImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.api.support.membermodification.strategy.impl;
+
+import org.powermock.api.support.MethodProxy;
+import org.powermock.api.support.Stubber;
+import org.powermock.api.support.membermodification.strategy.MethodStubStrategy;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+public class MethodStubStrategyImpl<T> implements MethodStubStrategy<T> {
+
+ private final Method method;
+
+ public MethodStubStrategyImpl(Method method) {
+ if (method == null) {
+ throw new IllegalArgumentException("Method to stub cannot be null.");
+ }
+ this.method = method;
+ }
+
+ @Deprecated
+ @Override
+ public void andReturn(T returnValue) {
+ toReturn(returnValue);
+ }
+
+ @Override
+ public void toThrow(final Throwable throwable) {
+ InvocationHandler throwingInvocationHandler = new InvocationHandler() {
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ throw throwable;
+ }
+ };
+ MethodProxy.proxy(method, throwingInvocationHandler);
+ }
+
+ @Override
+ public void toReturn(T returnValue) {
+ Stubber.stubMethod(method, returnValue);
+ }
+}
diff --git a/changelog.txt b/changelog.txt
new file mode 100644
index 0000000..723d191
--- /dev/null
+++ b/changelog.txt
@@ -0,0 +1,605 @@
+Change log 1.6.5 (2015-04-30)
+-----------------------------
+* Add ability to chain returns with doReturn() (thanks to "gauee" for pull request) (issue #599)
+* Code quality improvement, @Override annotation should be used on any method overriding (since Java 5) or implementing (since Java 6) another one
+* PowerMockRunner now processes JUnit Rules correctly (thanks to Stefan Birkner for pull request) (issue 427)
+* Added support for @TestSubject in EasyMock API. This is the equivalent of @InjectMocks in Mockito (big thanks to Arthur Zagretdinov for pull request)
+* Added experimental support for mockito 2.x
+* Ensuring JVM method size limit is never exceeded. Throw an user frendly exception if method size is exceeded. (thanks to Tomasz Przybyla for pull request) (issue #661)
+* Fix #214: Whitebox.invokeConstructor may not work as expected with overloaded constructors
+* Fix #352: PowerMockRunner should run tests defined in super class
+* Fix #510: Static method mocking with Mockito 1.9.5 and Powermock fails with Java 8 Consumer Interface
+* Fix #512: @PrepareForTest on method not working with PowerMockRule
+* Fix #652: PowerMock stubbing void method don't work for overloaded methods
+* Fix #648: TestNG SkipException doesn't work with PowerMock
+* Fix #634/#632: Add workaround as fix for Mockito 1+. Wait fix from Mockito team for Mockito 2.
+* Fix #590: suppress(method) doesn't work on a @Spy/PowerMockito.spy
+* Upgraded commons-logging dependency to version 1.2
+* Upgraded objenesis dependency to version 2.2
+* Upgraded TestNG dependency to version 6.9.10.
+* Upgraded xStream dependency to version 1.4.9.
+* ASM for PowerMock Javaagent repackaged from new version 5.0.4
+
+Change log 1.6.4 (2015-12-11)
+-----------------------------
+* DelegatingPowerMockRunner now implements Filterable interface to allow running for example individual test methods (thanks to chang-chao for pull request)
+* Fixed jacoco/powermock integration issue (thanks to Evgeny Astafyev for pull request)
+* Improvements to StackTraceCleanerProvider which cleans powermock classes from a stack trace
+* Replaced usage of uberjar mockito-all with mockito-core (thanks to Petr Široký and René Scheibe for helping out)
+* Code quality improvement, constructors only call non-overridable methods (thanks to Christian Ivan for pull request)
+
+Change log 1.6.3 (2015-10-02)
+----------------------------
+* Mock name in @Mock(name="abc") annotations are no longer ignored for the Mockito API extension
+* Fixed NPE in withArguments() constructor (thanks to Tomoyuki Saito for pull request)
+* Upgraded Javassist dependency to version 3.20.0-GA.
+* Using soft reference in classloader cache
+* MockClassloader now extends Javassist Loader classloader to implement findClass etc
+* PowerMock now works better with ByteBuddy (issue 579)
+* This allows creating mocks in the applyInterceptionPolicy method of MockPolicy, which in turn allows using MockPolicy together with PowerMockRule (issue 581).
+* Upgraded the powermock-easymock extension to use EasyMock 3.4
+
+Change log 1.6.2 (2015-01-03)
+----------------------------
+* PowerMockRunnerDelegate annotation now uses @Inherited (thanks to Henrik Kaipe for pull request)
+* Tests can now have multiple constructors (thanks to Henrik Kaipe for pull request)
+* Cleanup pom files and added version numbers (thanks to René Scheibe for pull request)
+* Fix "Test class can only have one constructor" issue that occurs when a JUnit or 3rd-party delegate runner (specified by a PowerMockRunnerDelegate annotation) can only deal with one public constructor. (thanks to Henrik Kaipe for pull request)
+* Packaged some of the Mocktio classes internally since Mockito is moving from CgLib to ByteBuddy. (thanks to Brice Dutheil for the pull request).
+* Upgraded Javassist dependency to version 3.19.0-GA.
+* Upgraded TestNG dependency to version 6.8.21.
+* The PowerMock EasyMock Api now depends on EasyMock 3.3.1.
+
+Change log 1.6.1 (2015-01-03)
+----------------------------
+* The PowerMock EasyMock Api now depends on EasyMock 3.3. Note that 1.6.0 also works with this version of EasyMock _if_ cglib-nodep 2.2.2 is used as EasyMock transitive dependency.
+* PowerMock JUnit Module now supports JUnit 4.12 (Thanks to Henri Tremblay for the pull request).
+* Upgraded TestNG from 6.8.8 to 6.8.13.
+* Fixed Mockito 1.10.9+ incompatibility, by repackaging CGLIB MockMaker (issue 524). Thanks to Brice Dutheil for the pull request.
+
+Change log 1.6.0 (2014-11-27)
+-----------------------------
+* It's now possible to verify private final overloaded methods in the Mockito Extension API. For example:
+ verifyPrivate(tested).invoke(method(MyClass.class, "myOverloadedMethodName", String.class, String.class)).withArguments(anyString(), captor.capture());
+* Upgraded Mockito API extension to work with version Mockito 1.10.8.
+* PowerMock now builds for Java 6 and not Java 5.
+* You can now use other runners in combination with the PowerMockRunner without using a JUnit Rule. This leaves the actual test-execution to or another runner of your choice.
+ For example tests can delegate to "SpringJUnit4ClassRunner", "Parameterized" or the "Enclosed" runner. This also allows PowerMock to (without any modifications) support future new JUnit-features from day one! Usage example:
+
+ @RunWith(PowerMockRunner.class)
+ @PowerMockRunnerDelegate(Parameterized.class) // Use the parameterized JUnit in combination with the PowerMockRunner
+ @PrepareForTest(SuppressConstructorDemo.class)
+ public class SuppressConstructorDemoTest {
+ ...
+ }
+ (Big thanks to Henrik Kaipe for this excellent pull request).
+
+Change log 1.5.6 (2014-09-04)
+-----------------------------
+* Changed so that the MockClassLoader throws ClassNotFoundException instead of Javassist's NotFoundException when a class isn't found (thanks to Mikael Petterson for the pull request).
+* Final equals methods should now work with Mockito and not cause stackoverflow (thanks to Peer Hartmann for pull request)
+* Removed redundant cast when creating a class replicas for final system classes.
+* Cleaned up some code in the ClassReplicaCreator class
+* Added support for answers, name and extract interfaces in PowerMockito when using annotations (@Mock). Note that answers doesn't work for final classes or methods! (issue 486).
+* PowerMockIgnore is now taken into account when using the Java Agent PowerMockRule.
+* Improved java agent automatic bootstrap mechanism to work better for newer JDK's.
+* PowerMock now finds default methods in Java 8 (issue 513).
+* Annotations such as @Mock and @InjectMocks can now be used with the JUnit Java Agent.
+* Proxy framework is loaded from the the JUnit Java Agent which means that all Whitebox methods work as expected.
+
+Change log 1.5.5 (2014-05-28)
+-----------------------------
+* Updated OSGi metadata
+* MockClassLoader.getResources no longer loads same file twice (thanks to Kelsey Rider for the patch)
+* Added getResourceAsStream and getResource to DeferSupportingClassLoader which defers loading to the deferring classloader.
+* Added ability to adjust the classpath when running the a test using the @UseClassPathAdjuster annotation. This is useful when integrating PowerMock with certain third-party JUnit runners (thanks to Jonas Berlin for the patch).
+* Upgraded to Javassist 3.18.2-GA.
+* Moved project to github (issue 493).
+* Upgraded to TestNG 6.8.8.
+* Removed accidental JUnit dependency to Objenesis and XStream classloading projects.
+
+Change log 1.5.4 (2014-01-29)
+-----------------------------
+* Removed OSGi metadata because they didn't work properly
+* Fixed an issue when setting up private method expectations with multiple arguments in Mockito.
+* Added support for suppressing static initializers using TestNG (issue 256) (thanks to majorpetya for the patch).
+* PowerMock Java agent works in Java 8 (issue 475) (thanks to iirekm for help).
+* Moved bundled asm packages into the powermock package for the PowerMock Java Agent module to avoid classloading issues.
+
+Change log 1.5.3 (2014-01-10)
+-----------------------------
+* Added OSGi metadata to manifest files (issue 204) (thanks to Gabor Liptak for patch)
+* Upgraded to Javassist 3.18.1-GA.
+* Test case with expectedExceptions no longer fails when using PowerMock with TestNG (issue 366) (thanks to majorpetya for the patch).
+* Fixed a classloading issue with the JUnit4TestSuiteChunkerImpl (thanks to Robert Gay for the patch)
+* Updated objenesis to version 2.1
+
+Change log 1.5.2 (2013-11-18)
+-----------------------------
+* Fixed PowerMock OOM (OutOfMemory) issues with Mockito (big thanks to Henrik Karlsson for the patch).
+* PowerMock EasyMock extension API now supports EasyMock version 3.2.
+* Added jacoco agent to be deferred by the PowerMock classloader
+* Updated TestNG dependency to 6.8.7.
+
+Change log 1.5.1 (2013-06-19)
+-----------------------------
+* Maven no longer adds classpath to jar manifests when building PowerMock (issue 413).
+* PowerMockRunner now supports both MethodRules and TestRules to comply with JUnit 4.11 (thanks to "Boris Code" for the patch) (issue 419).
+* Slf4j MockPolicy in Mockito now works again (issue 431).
+* Removed synchronized from all MockGateway methods in order to make it work with multi-threaded Mockito.
+* The PowerMock runner for JUnit now supports assumeTrue(..) statements (issue 408).
+* Mocked system classes are now invoked when it's casted into another (non-final) type (thanks to Jonatan Jonsson for the patch) (issue 445).
+* TestNG state is cleaned up in a better way when a test fails (thanks to Jonatan Jonsson for the patch).
+* PowerMock byte-code manipulation transformers now ignores classes it cannot load. This means that PowerMock works with better SPI's that have compile-time dependencies that are not available at runtime.
+* Upgraded Javassist to version 1.8.0-GA.
+* Upgraded to TestNG module to version 6.8.5
+* Upgraded to JUnit module to version 4.11
+
+Change log 1.5 (2012-12-04)
+---------------------------
+* Added var-args to mockStatic in the PowerMockito API. You can now do:
+ mockStatic(A.class, B.class, C.class);
+* Suppression is now working for overridden methods (issue 364, 51). Thanks to hpbeem for the patch.
+* PowerMock junit module now supports JUnit rules for version 4.9+ (issue 344). Thanks to Andreas Kutschera for the patch.
+* Fixed is with PowerMock JUnit runner that failed to parse JUnit versions including characters such as 4.9b2. (issue 381).
+* Mockito extension API now uses Mockito 1.9.5 (issue 398)
+* Updated TestNG dependency to version 6.8
+* Added support for easily mocking all constructors of a class in the Mockito extension API. For example: whenNew(X.class).withAnyArguments().thenReturn(xMock); (issue 405).
+* Upgraded to Javassist 3.17.1-GA, this means that PowerMock works in Java 7!
+
+Change log 1.4.12 (2012-04-05)
+------------------------------
+* Really added missing class, PowerMockTestCase, to testng full release jar (issue 327).
+* PowerMock JUnit module now works with JUnit 4.10 (thanks to Diego Coronel for the patch) (issue 367)
+* Changed name from org.powermock.api.mockito.mockpolicies.Slf4jMockPolicy to org.powermock.api.mockito.mockpolicies.Slf4jMockPolicy in the Mockito extension API.
+* Upgraded Javassist to version 3.16.1.GA.
+* DeferSupportingClassLoader now overrides ClassLoader.findResources() which enables classes loaded by MockClassLoader to be to find resources via ClassLoader.findResources(...). Thanks to wrussellmorris for the patch (issue 380).
+* Updated TestNG dependency to version 6.4
+
+Change log 1.4.11 (2012-01-05)
+------------------------------
+* Fixed an OutOfMemory issue in PowerMockRunner (issue 346).
+* Added Sfl4jMockPolicy to the Mockito extension API, thanks to Alexandre Normand for the patch.
+* Replaced ${version} to ${project.version} in all pom files (thanks to pvdissel for the patch) (issue 287).
+* Added work-around to stub some final system classes (such as java.util.UUID) (issue 354).
+* Improved the PowerMock Java agent support. It should now work together with multiple java agents (thanks to Magnus Jungsbluth for the patch) (issue 357).
+* Upgraded TestNG module to 6.3.1.
+* Upgraded EasyMock extension API to use version 3.1 of EasyMock. This version should fix a couple of OutOfMemory issues.
+* PowerMockito is updated to use Mockito 1.9.0
+* setUp-method with @Before annotation is no longer executed twice when extending TestCase (issue 356)
+* Upgraded classloader xstream deepcloner to XStream 1.4.2 (issue 345)
+
+Change log 1.4.10 (2011-08-23)
+------------------------------
+* Added missing class, PowerMockTestCase, to testng full release jar (issue 327).
+* Fixed test initialization error when using PowerMock Mockito API in Ant (issue 333).
+* Upgraded to Javassist 3.15 GA (issue 338).
+* Upgraded TestNG module to TestNG 6.2.
+* Mockito @InjectMocks annotations on superclasses of test class are no longer ignored (issue 343).
+* MockClassloader now defers the loading of classes in "org.pitest.*" to the system classloader. This means that you should be able to use PIT (http://pitest.org) without adding @PowerMockIgnore("org.pitest.*") to each test class (issue 337).
+* PowerMockito now works with Mockito 1.9-rc1 but will not include the new artifact by default because it's still rc (issue 339).
+* Removed PowerMockRule from full jar in release process (issue 325).
+
+Change log 1.4.9 (2011-05-02)
+-----------------------------
+* Fixed an issue when mocking system classes containing fields of type Class, Classloader or synthetic fields such as java.util.ServiceLoader.
+* TestNG PowerMockObjectFactory now sets the thread context classloader to the PowerMock mock classloader (issue 315).
+* TestNG PowerMockObjectFactory now only uses PowerMock classloader and byte-code manipulation if the test class or a method declared in this method is annotated with @PrepareForTest or @SuppressStaticInitializerFor. This introduces a non-backward compatible change so if you're currently using mock injection (e.g. annotating a field with @Mock) you must now also use @PrepareForTest or @SuppressStaticInitializerFor for the mocks to be injected (issue 299).
+* Upgraded TestNG module to TestNG 6.0.1 (issue 316).
+* Fixed an issue with the PowerMock JUnit runner that prevented a JUnit Rule to throw an exception failing the test (issue 311).
+* Fixed an issue with test state clearing while running a PowerMock enabled test as an Eclipse PDE test (issue 309).
+* Classloader based PowerMock JUnit Rules now supports suppressing static initializers
+* Improved state clean-up in TestNG module when extending from PowerMockTestCase.
+* Automatic creation and injection of mocks to a field annotated with @Mock does no longer work if you're not extending from PowerMockTestCase in the TestNG classloading module (side-effect of issue 299).
+* Removed the classloading version of PowerMockRule from the powermock-easymock-full and powermock-mockito-full release jars. You need to download the rule implementations manually since there are now two different implementations to choose from. (issue 318)
+* Implemented experimental support for bootstrapping PowerMock using a Java agent. With the agent you won't run into classloading issues that you may with the standard way of bootstrapping. The new project is called junit4-rule-agent for JUnit and testng-agent for TestNG.
+
+Change log 1.4.8 (2011-02-26)
+-----------------------------
+* Fixed a bug in Whitebox which prevented passing null parameters to methods.
+* PowerMock now supports mocking static final inner classes and member Enums (issue 95).
+* Fixed a bug in PowerMockito that sometimes caused the finalize method to be called instead of the expecting method when setting up expectations (issue 308).
+* Upgraded TestNG module to TestNG 5.14.6
+
+Change log 1.4.7 (2010-12-27)
+-----------------------------
+* The MemberModifier API now checks that the replacing method returns the same type and have the same number of parameters as the original method otherwise an IllegalArgumentException is thrown (issue 285).
+* Fixed a bug which made it impossible to mock private methods with multiple arguments (issue 289).
+* Removed some unwanted debug messages from the TestNG module.
+* Updated javadoc in Whitebox and WhiteboxImpl.
+* EasyMock and Mockito extension API now supports mocking new invocations with var args parameters when var args paramters is not the first parameter (issue 163).
+* Various improvements to var args handling for both methods and constructors.
+* Upgraded to Javassist 3.14 (issue 295).
+* Upgraded junit module to use JUnit 4.8.2 (issue 296).
+* You no longer need to prepare system classes that are not final and whose methods are not static, final or native in a special way (by prepare the class calling the system class method) (issue 300).
+* Added method "defaultConstructorIn" to the MemberMatcher API so that you can e.g. suppress a default constructor using suppress(defaultConstructorIn(SomeClass.class)) (issue 302).
+* PowerMock now cleans up EasyMock state after each test case which significantly decreases memory consumption.
+* PowerMock now cleans up most Mockito state after each test case which decreases memory consumption.
+* Major refactoring of the classloading module. It has been split up in a way that allows for different object deep-cloning mechanisms. The previous implementation is now called powermock-classloading-objenesis and there's also a new one called powermock-classload-xstream. The latter uses X-Stream for deep-cloning. This means that if you're using the PowerMock JUnit Rule you must also depend on one of the two deep-cloner implementations.
+
+Change log 1.4.6 (2010-10-13)
+-----------------------------
+* Changed project structure, all group id's are now "org.powermock" but most artifact id's are the same. There are two exceptions, org.powermock.tests and org.powermock.examples. Artifact module-test-powermock has been renamed to module-test-easymock and module-test-powermockito has been renamed to module-test-mockito (issue 234).
+* Removed all third-party repositories from the pom's to allow for Maven central syncing.
+* PowerMock can now be built with Maven 3 (issue 283).
+* Prepared pom's for Maven central synching.
+* Upgraded the TestNG module to version 5.14 (issue 275).
+* Fixed a bug in Whitebox which caused some overriden methods to be treated as overloaded (issue 276).
+
+Change log 1.4.5 (2010-08-30)
+-----------------------------
+* The EasyMock API extension should now work when testing Eclipse plugins and running the tests as PDE (JUnit Plugin) tests (issue 264)
+* Deprecated "andReturn" in the stubber API and added "toReturn" instead. The API now reads e.g. "stub(method("methodName")).toReturn(new Object());"
+* Added the "toThrow" method to the stubber API. You can now do e.g. "stub(method("methodName")).toThrow(new Exception());" (issue 182)
+* Whitebox#setInternalStateFromContext now support field matching strategies. By default all context fields that matches a field in the target class or instance is copied to the instance. If the strategy is changed from MATCHING to STRICT then an exception will be thrown if the context contains a field that cannot be copied to the target. Note that this change may cause backward incompatibility if you're currently using setInternalStateFromContext in your code. (issue 221)
+* Fixed an issue that was introduced in version 1.4 when support for partial mocking of instance methods in final system classes not having a default constructor was added. The bug caused an javassist.CannotCompileException exception when mocking certain classes such as java.lang.Console (issue 272).
+* Removed PowerMock specific classes to support mocking of signed classes in the EasyMock extension API since nowadays EasyMock supports this out of the box. This makes PowerMock less dependent on a specific EasyMock version and fixes and patches in EasyMock automatically applies to PowerMock in the future as well. (issue 273)
+* Upgraded the TestNG module to version 5.13.1.
+* Whitebox#newInstance(..) now supports instantiating interfaces and arrays. An exception is thrown when trying to instantiate an abstract type (issue 193).
+
+Change log 1.4 (2010-07-22)
+---------------------------
+* Implemeted support for mocking instance methods of final system classes with the Mockito extension API (issue 169)
+* Partial mocking of instance methods in final system classes not having a default constructor now works in the EasyMock extension API (issue 170)
+* The deep cloner can now clone java.reflect.Method objects correctly to a different classloader.
+* Fixed a critical bug in the ClassloaderExecutor which prevented it from running methods returning void. This affected the PowerMockRule which prevented it from executing test methods (even though it looked like it did) (issue 268, also closes issue 245)
+* Upgraded to Javassist 3.13 (issue 269)
+* Fixed some problems with Withbox regarding invocation of var args member class constructors and methods (issue 267).
+* Partial mocking of public static methods now works in Mockito (issue 261)
+* Better clean-up in test runner which fixes some java.lang.OutOfMemoryError errors in large test suites.
+
+Change log 1.3.9 (2010-07-14)
+----------------------------------
+* Upgraded the Mockito extension API to support Mockito 1.8.5
+* Upgraded the EasyMock extension API to support EasyMock 3.0 (issue 259)
+* Spying with PowerMockito now retains object state (issue 263)
+
+Change log 1.3.8 (2010-05-13)
+-----------------------------
+* Fixed a bug in DeepCloner which caused a NullPointerException for arrays containing null values.
+* Changed groupId of the PowerMock JUnit Rule project to org.powermock.modules.
+* Included PowerMock rule in the released artifacts
+* verifyNew with arguments no longer throws NullPointerException when missing expectation in the Mockito extension API.
+* EasyMock API extension now supports mock creation of classes whose hashCode implementation depends on constructor initialization.
+* It's now allowed to use verifyNew multiple times just as with verify in standard Mockito (issue 251)
+* Mockito extension API now supports mocking and stubbing equals and hashcode.
+* Fixed an issue in the core mock classloader that accidentally caused any previous deferred packages to be overwritten when adding new packages to be ignored.
+* Upgraded to Javassist 3.12 (issue 254)
+* Upgraded to TestNG 5.12 (issue 250)
+* Improved error messages in TestNG when running inside Eclipse
+
+Change log 1.3.7 (2010-03-22)
+-----------------------------
+* Added support for JUnit 4.8.1 (issue 226)
+* Added support for Mockito 1.8.4
+* Fixed so that a "mock name" is set in the Mockito extension API. Fixes NullPointerException when e.g. toString is invoked on a mock. (issue 239)
+* Changed method signature on "mockStatic" to return void in the Mockito extension API.
+* Fixed the "Internal error: Run delegates were 0" bug when using a test class hierarchy and the PowerMock JUnit runner when no tests are defined in a parent test class (issue 241).
+* Added support for deep cloning objects containing self references using the DeepCloner.
+* New experimental approach for bootstrapping PowerMock is supported using a JUnit rule called PowerMockRule (available in JUnit 4.7+). This allows you to use other JUnit runners than the PowerMock one (PowerMockRunner) while still benefiting from PowerMock's functionality.
+* Added support for suppressing all constructors in a class using suppress(constructorsDeclaredIn(X.class)).
+* Added support for suppressing all constructors and methods in a class suppress(everythingDeclaredIn(X.class)).
+
+Change log 1.3.6 (2010-03-10)
+-----------------------------
+* Added testng to full release project.
+* Fixed so that classloader executor supports runnable's.
+* DeepCloner now supports reference cloning.
+* DeepCloner now supports cloning enum constants.
+* DeepCloner now supports cloning standard java types (using simple serialization).
+* DeepCloner now supports cloning fields in a hierarchy.
+* DeepCloner now supports cloning class fields.
+* Fixed a bug in the Wildcard matcher which resulted in that classes located in packages containing "junit.", "java.", "sun." in their name was never prepared for test (issue 225).
+* Fixed so that you can mock anonymous inner classes with the Mockito API extension (issue 227).
+* Nested classes declared inside the test case are automatically prepared for test.
+* Minor improvement in the byte-code manipulation; only package private classes are changed to public.
+* Upgraded he EasyMock extension API to use EasyMock class extension 2.5.2 (due to internal changes in EasyMock it's not backward compatible with older versions).
+* Upgraded to Objenesis for powermock-reflect to 1.2.
+* Fixed so that MockGateway now finds the correct method to invoke when several overloaded method candidates are found (issue 229).
+* Upgraded to Mockito 1.8.3.
+* Added support for Mockito annotations @Spy, @Captor and @InjectMocks.
+* Mockito extension now supports real partial mocking for private (and private final) methods (both static and instance methods) using PowerMockito.doReturn(..), PowerMockito.doThrow(..) etc.
+* Added support for MockSettings and Answers when creating class or instance mocks in Mockito extension, e.g. "FinalClass mock = mock(FinalClass.class, Mockito.RETURNS_MOCKS);".
+
+Change log 1.3.5 (2009-12-13)
+-----------------------------
+* Removed EasyMock maven dependencies from the JUnit legacy runner since they're not needed.
+* Fixed a bug in WhiteboxImpl#findUniqueConstructorOrThrowException which caused an additional constructor to be found when a class was prepared for test (issue 189).
+* Fixed the maven assembly so that it now produces two full jar files, one for Mockito and one for EasyMock. These contains the sources as well.
+* Mockito extension API now supports Mockito 1.8.1 & 1.8.2.
+* java.lang.Object#getClass is no longer mockable by default. The reason is that it may lead to an unexpected method invocation exception using EasyMock in some equal implementations. It's possible to override this behavior.
+* DeepCloner should now support cloning of static final fields on SUN JVM.
+* Fixed a minor bug in Whitebox#getInternalState so that a better error message is given when the instance argument is null (issue 205).
+* Fixed some typos in the javadoc of PowerMockito#verifyNew (issue 187).
+* Fixed so that Whitebox#getInternalState(..) now supports passing in super types as field-type critiera (issue 210).
+* Fixed so that Whitebox#getInternalState(..) and Whitebox#setInternalState(..) doesn't cause NPE when too many fields matched the criteria (issue 211).
+* Basic support for TestNG (5.11) implemented.
+* Fixed so that Whitebox#invokeMethod now works for overridden methods.
+* Implemented findResource in classloader, this means that you should be able to locate resources in classpath (issue 143).
+* JUnit runner and TestNG object factory now clears MockRepository state upon instantiation. This is useful in cases where a previous test has used e.g. PowerMock#createMock(..) to create a mock without using the runner/factory which means that there would be some state left in the MockRepository that hasn't been cleared.
+
+Change log 1.3.1 (released 2009-10-28)
+--------------------------------------
+* Critial bug resolved in the PowerMock JUnit 4.7 runner: Before tests would not be executed at all if a JUnit rule was used in the test (even though it looked like they were). This has now been resolved an thus support for JUnit 4.7 rules should _really_ work.
+* DeepCloner now supports cloning of one dimensional arrays, primitives, enums and collections.
+* Test case is now always prepared for test even if no @PrepareForTest annotation is specified
+* Fixed a bug in Whitebox#setInternalState so that it now works to supply an array when specifying a method name again.
+* Improved javadoc in Whitebox class
+* Upgraded EasyMock extension API to depend on EasyMock 2.5.2 (EasyMock class extensions are still version 2.4 since that's the latest release right now).
+
+Change log 1.3 (released 2009-10-06)
+------------------------------------
+* Classes that will have their static initializers suppressed are automatically added to prepare for test in mock policies.
+* Added a toString implementation for TestMethodResultImpl
+* Added a toString implementation for TestSuiteResultImpl
+* suppressMethod(Class...classes) now takes a class and additional classes as var args (i.e. suppressMethod(Class cls, Class...classes). This makes it easier to suppress all methods of a particular class for only one class.
+* Invoking reflection methods now works again. This failed in version 1.2 and 1.2.5 when PowerMock begun supporting mocking of system classes. E.g. MyClass.class.getClassloader() now works again even if MyClass is prepared for test.
+* The standard JUnit 4 runner has been verified to work with JUnit 4.6 and 4.7. The version dependency for JUnit4 is thus changed from [4.4,4.5] to [4.4,4.7].
+* Classes prepared for test in parent test classes are now automatically prepared for test as well. I.e. if Test Case A extends Test Case B and A prepares X.class and B prepares Y.class then both X and Y will be prepared for test. Before only X was prepared for test.
+* Fixed a bug in Whitebox which prevented it from instantiating classes with constructors combining normal and var-arg parameters. The same was fix was applied to method invocations as well.
+* Fixed so that WhiteboxImpl#findMethodOrThrowException(..) throws a TooManyMethodsFoundException if a potential method had previously been found and a new matching var-args method was found.
+* Fixed so that WhiteboxImpl#findConstructorOrThrowException(..) throws a TooManyConstructorsFoundException if a potential constructor had previously been found and a new matching var-args constructor was found.
+* Fixed a bug so that when Whitebox looks for a var args method it now also checks that the component type of the var args array is the same as the supplied argument type(s).
+* Implemented so that expectPrivate in the EasyMock extension API can be used without specifying a method name. The method is looked up by using the argument types.
+* Extended the Whitebox.setInternalState functionality to accept a var-args list of values to set on an object. I.e. you can now do Whitebox.setInternalState(object, myState1, .., myStateN).
+* Upgraded to Javassist 3.10 (3.11 doesn't work with PowerMock due to a bug or backward incompatibility in Javassist).
+* Fixed a bug in the EasyMock extension API regarding suppression of methods so that it now uses Whitebox.getMethods(..) instead of Whitebox.getMethod(..).
+* Mocking of static methods in final system classes now works with the Mockito extension (because of a bug fix in Javassist 3.10)
+* PowerMock now changes the context class-loader to the MockClassloader which means that you don't need to use @PowerMockIgnore as often as before. This solves many issues with frameworks that creates new instances using reflection like log4j, hibernate and many XML frameworks. This fix is not backward compatible with version 1.2.5! If you've been using PowerMockIgnore in your test you may need to remove it (or update the ignored package list) otherwise the test might fail.
+* Implemented support for setting internal state from a context (using Whitebox.setInternalStateFromContext(..)).
+* Error message differ between static or instance type fields when internal state cannot be set because a field wasn't found.
+* PowerMock now supports mocking instance methods of final system classes (such as java.lang.String). To do this you need to prepare the class that invokes the method of the system class. Note that partial mocking of instance methods in final system classes doesn't yet work if a constructor needs to be invoked on the mock.
+* You can now mock new instance calls to final system classes in the same was you'd mock any other new instance call.
+* Improved error message in Whitebox when getting a method or constructor which was not found and no parameter types were supplied.
+* The state of classes that should have their static intializers suppressed are no longer clear after each atomic test. This means that suppression of static initializers works (again) in test suites.
+* Begun working with support for TestNG (thanks to Dan Fabulich for helping us with this).
+* Deprecated Whitebox#getInternalState(Object object, String fieldName, Class<?> where, Class<T> type), use "Whitebox.<Type> getInternalState(Object object, String fieldName, Class<?> where)" instead.
+* Changed return type of Whitebox#getInternalState(Object object, String fieldName) from Object to T. This means that you can avoid cast using e.g. "Whitebox.<MyType> getInternalState(instance, "myFieldName")".
+* Changed return type of Whitebox#invokeMethod(..) from Object to T. This means that you can avoid cast using e.g. "Whitebox.<MyType> invokeMethod(..)".
+* JUnit test runner now supports JUnit 4.7 rules
+* Upgraded the Mockito extension to use Mockito 1.8
+* Created a reusable component (PowerMockIgnorePackagesExtractorImpl) that can be used by test runners to extract which packages that should be ignored in a test case.
+* Removed mockStatic(Class<?> type, Method method, Method... methods), mockStaticPartial, mockPartial, mock(Class<T> type, Method... methods) & mock(Class<T> type, Method... methods) from the Mockito extension API. You should use PowerMockito.spy instead.
+* When using the PowerMock Mock annotation with Mockito the method names (previously used for partial mocking) are ignored. They are no longer needed, just use PowerMockito.spy instead.
+* Mockito extension API support for private methods expectations using PowerMockito.when(..).
+* Fixed so that Whitebox error message prints correct parameter types when a MethodNotFoundException is thrown if a method with correct name but wrong parameter types were specified.
+* EasyMock extension API: You can now manually use replay(..) or verify(..) and then fall back on replayAll(..) verifyAll(..) even if a mock has previously been replayed/verified. I.e. replayAll/verifyAll only replays and verifies mocks that has previously not been manually replayed/verified.
+* WhiteboxImpl#getField(..) now check for null returned from Class.getSuperclass() to avoid NullPointerException when type is an interface (thanks to Ben Chatelain for the patch)
+* Deprecated org.powermock.core.classloader.annotations.Mock, you should now use the Mock annotation in respective extension API instead. For EasyMock this is org.powermock.api.easymock.annotation.Mock and for Mockito it's org.mockito.Mock.
+* Packages ignored for test in parent test classes are now automatically ignored as well when using @PowerMockIgnore. I.e. if Test Case A extends Test Case B and A ignores X and B ignores Y then both X and Y will be ignored in the test case. Before only X was ignored.
+* The method IExpectationSetters<Object> expectNew(String fullyQualifiedName, Object... arguments) in the EasyMock extension API changed return type to <T> IExpectationSetters<T> expectNew(String fullyQualifiedName, Object... arguments).
+* Improved error message for Whitebox#getConstructor when no constructor was found.
+* Fixed a bug in PowerMockito's CgLibProxyFramework#getUnproxiedType(..) so that it now _really_ returns the unproxied type.
+* You can now mock construction of new objects using the Mockito extension. To do so use PowerMockito#whenNew(..), e.g. whenNew(MyClass.class).withArguments(myObject1, myObject2).thenReturn(myMock). Verification can be done with PowerMockito#verifyNew(..), e.g. verifyNew(MyClass.class).withArguments(myObject1, myObject2).
+* Annotation support has been integrated in the test runners (both for JUnit and TestNG) so there's no need to specify the AnnotationEnabler listener using @PowerMockListener(AnnotationEnabler.class). It works both for the EasyMock and Mockito extension API's. This means that org.powermock.api.easymock.powermocklistener.AnnotationEnabler and org.powermock.api.mockito.powermocklistener.AnnotationEnabler has been deprecated.
+* Whitebox#getInternalState(..) and Whitebox#setInternalState(..) now uses isAssignableFrom instead of equals when looking for field types.
+* Added a new api-support project that contains functionality shared between all mock API projects
+* Mockito extension API now supports suppressing constructors, fields and methods.
+* ProxyFramework is now registered from the test runner instead of the extension API. This means that Whitebox always works correctly in the test cases regardless if the mock api is used or not.
+* Test classes are now always prepared for test automatically. This means that you can use suppressConstructor(..) and mock final system classes more easily since you don't have to prepare the actual test class for test. In some cases this change is not backward compatible with version 1.2.5. These cases are when you've tried to suppress a constructor but have forgot to prepare the test class for test as well.
+* @PowerMockIgnore now accept wildcards, this means that if you want to ignore all classes in the "com.mypackage" package you now have to specify @PowerMockIgnore("org.mypackage.*") (before you did @PowerMockIgnore("org.mypackage.")).
+* @PrepareForTest now accepts wildcards in the fullyQualifiedName attribute, e.g. you can now do @PrepareForTest(fullyQualifiedName={"*name*"}) to prepare all classes in containing "name" in its fully-qualified name.
+* Fixed a major issue with the prepare for test algorithm. Before classes were accidentally prepared for test automatically if the fully qualified name of the class started with the same fully qualified name as a class that were prepared for test. This has now been resolved. This may lead to backward incompatibility issues in cases where tests didn't prepare all necessary artifacts for test.
+* Mockito extension API now supports verification of private methods (for both static and instance methods). Use verifyPrivate(..).invoke(..), e.g. verifyPrivate(myObject, times(2)).invoke("myMethod", argument1, argument2).
+* Verification behavior of static method in the Mockito extension API has changed. Before you did "verifyStatic(MyClass.class); MyClass.methodToVerify(argument);", now you do "verifyStatic(); MyClass.methodToVerify(argument);". You can also pass a verification mode when verifying static methods: "verifyStatic(times(2)); MyClass.methodToVerify(argument);". This change is NOT backward compatible with version 1.2.5.
+* Mockito extension API now supports "verifyNoMoreInteractions" and "verifyZeroInteractions" for both instance mocks, class mocks and new instance mocks.
+* Deprecated setSubstituteReturnValues, getSubstituteReturnValues and addSubtituteReturnValue in MockPolicyInterceptionSettings, you should now use setMethodsToStub, getStubbedMethods and stubMethod instead.
+* Renamed MockRepository#getSubstituteReturnValue to getMethodToStub and MockRepository#putSubstituteReturnValue to putMethodToStub.
+* PowerMockito now supports, doAnswer, doThrow, doCallRealMethod, doNothing and doReturn for void methods defined in final classes, final void methods and static methods. Note that if a method is a private void method you should still use PowerMockito#when.
+* Removed the deprecated classes "org.powermock.PowerMock" and "org.powermock.Whitebox".
+* PowerMock support API now has a DeepCloner class that you can use to create a clone of an object. This clone can also be cloned to a different classloader.
+* Added a PowerMock classloading project which can be used to execute any Runnable or Callable in a different classloader. The result of a callable operation will be cloned to the the callers classloader.
+* Mocking static methods in final system classes works in the Mockito extension API.
+* AnnotationEnablers only injects to fields that haven't previously been set (i.e. if the field is null).
+* Added org.powermock.core.spi.listener.AnnotationEnablerListener interface that all AnnotationEnablers must implement.
+* Implemented a fluent API for suppression, replacing and stubbing (org.powermock.api.support.membermodification.MemberModifier). It uses matcher methods defined in org.powermock.api.support.membermodification.MemberMatcher. Some examples:
+ replace(method(X)).with(method(Y)); // Works only for static methods
+ replace(method(X)).with(invocationHandler);
+ stub(method(X)).andReturn(Y);
+ suppress(methodsDeclaredIn(X.class, Y.class))
+ suppress(method(X.class, "methodName"))
+ suppress(methods(method(X.class, "methodName"), method(Y.class, "methodName2")))
+ suppress(methods(X.class, "methodName1", "methodName2"))
+ suppress(field(..))
+ suppress(constructor(..));
+* Deprecated all suppressMethod, suppressField and suppressConstructor methods in the EasyMock extension API. You should now use PowerMock#suppress instead.
+* PowerMock and PowerMockito now supports stubbing methods (including private methods). Use PowerMock#stub or PowerMockito#stub to accomplish this.
+* PowerMock and PowerMockito now supports proxying methods, including private methods using replace(..), e.g. replace(method(MyClass.class, "methodToProxy")).with(myInvocationHandler). Every call to the "methodToProxy" method will be routed to the supplied invocation handler instead.
+* PowerMock and PowerMockito now supports duck typing of static methods, including static private methods using replace(..), e.g. replace(method(MyClass.class, "methodToDuckType")).with(method(MyOtherClass.class, "methodToInvoke")). Every call to the "methodToDuckType" method will be routed to the "methodToInvoke" method instead.
+* Mock policies now supports proxing methods using proxyMethod(..).
+* Private inner memeber interfaces are not changed to public anymore during the byte-code manipulation session
+* PowerMock JUnit4 Runner can now instantiate test classes that have a String constructor if the test class extends from junit.framework.TestCase.
+
+Change log 1.2.5 (released 2009-05-05)
+--------------------------------------
+* Mocking of static methods in final system classes such as java.lang.System now works. To do this you need to prepare the class that invokes the method of the system class as well as the actual test case.
+* Fixed a major issue with mock policies which caused them to fail if a test case had more than one test method. Also fixed so that mock policies works in "setup" methods.
+* Fixed so that WhiteboxImpl#getMethod no longer fails when invoking proxified interface methods declared in extended interfaces. Previously if e.g. interface A extended B & C and a method was declared in B it wouldn't be found by WhiteboxImpl#getMethod since it only used to traverse the class hierarchy and not the structure of the extended interfaces.
+* Whitebox#invokeMethod now works without specifying any method name which can increase the refactoring possibilities of the code when invoking unique private methods.
+* Fixed the error message when a method couldn't be found and only one method was specified (for example when using Whitebox.getMethods(MyClass.class, "onlyOneMethod")).
+* All field matcher strategies now throws FieldNotFoundException's instead of IllegalArgumentException's.
+* Upgraded the Mockito API extension to use Mockito 1.7.
+* Added mockPartial and mockStaticPartial to the Mockito API to allow for easier creation of partial mocks.
+
+Change log 1.2 (released 2009-01-30)
+------------------------------------
+* Upgraded to Javassist 3.9
+* The test result related artifacts were moved from package org.powermock.tests.result to org.powermock.core.spi.testresult.
+* Structural refactoring to remove Structure 101 XS: Moved org.powermock.api.easymock.internal.proxyframework.spi.ProxyFramework to org.powermock.reflect.spi.ProxyFramework.
+* Added PowerMock specific exceptions to the reflect project. Instead of getting RuntimeExceptions or IllegalArgument exceptions a more appropriate runtime exception is thrown. For example ConstructorNotFoundException or TooManyFieldsFoundException etc.
+* Whitebox.getMethods(..) and Whitebox.getFields(..) now throw an MethodNotFoundException if no method or field was found.
+* Error messages when expecting new now works correctly for inner classes.
+* Added three new methods to the Whitebox class, these are Whitebox.getInnerClassType(..), Whitebox.getLocalClassType(..) and Whitebox.getAnonymousInnerClassType(..). These methods helps with getting the class type for private inner, local or anonymous inner classes.
+* Inner member classes declared in class X are automatically prepared for test when X is prepared for test.
+* PowerMock now follows the semantics of EasyMock verification. This means that invoking an unexpected method of a mock object will cause an AssertionError to be thrown even if verify has been called prior to the method invocation.
+* Interfaces will now be bytecode manipulated if included in @PrepareForTest or @SuppressStaticInitializationFor. This is useful since interfaces can also contain evil static initializers (using bytecode manipulation or other tricks). Concrete example found in XMLBeans.
+* Fixed problem with infinite recursion with some hashCode implementations
+* Possible to mock non-final system classes such as java.net.URLEncoder. To do this you need to prepare the class that invokes the method of the system class as well as the actual test case.
+* Fixed a NPE bug in WhiteboxImpl#findSingleFieldUsingStrategy when the startClass was null and a field name haven't been found.
+
+Change log 1.1.1 (released 2008-12-15)
+--------------------------------------
+* Fixed maven version issues for the junit4-legacy module and junit3 module.
+* Fixed a major issue with PowerMock test listeners. The PowerMockTestListener.beforeTestMethod(..) was invoked too late which could cause a NullPointerException when invoking setup methods.
+* Updated javadoc (some errors in the java doc text).
+
+Change log 1.1 (released 2008-12-12)
+------------------------------------
+* Only signed classes are loaded by the signed supporting CGLib naming policy.
+* Whitebox.invokeConstructor now propagates InvocationTargetExceptions correctly.
+* Restructured release assemblies to include just the correct things.
+* Set sources:jar and javadocs:jar to run on every build.
+* LoggerTest now creates its test log file in ./target/ directory instead of ./
+* Major refactoring of project structure, it's now be possible to use PowerMock as a foundation for testability for other mock frameworks. PowerMock core is no longer coupled to EasyMock.
+* Fixed a serious issue with the classloading hierarchy of PowerMock's JUnit runners.
+* Implemented support for PowerMock test listeners, to create a listener you need to implement the org.powermock.core.spi.PowerMockTestListener interface and pass the implementation class to the PowerMockListener annotation.
+* Started Mockito integration. It supports final, static (non-void) and partial mocking using the PowerMock Mockito API. It also supports the Mockito annotations if using the @PowerMockListener(AnnotationEnabler.class) at the class-level of the test case.
+* Added a new Mock annotation which can be placed on fields to allow for a PowerMock listener to create and inject mock objects. Use the AnnotationEnabler listener from the EasyMock or Mockito API.
+* Exceptions are no longer wrapped in run-time exceptions when invoking a method using Whitebox.invokeMethod(..).
+* Major refactoring of the classloader structure and delegation.
+* Added two new methods to the Whitebox API, getAllInstanceFields and getAllStaticFields. One takes an object as parameter and one takes a class. They return all instance/class fields of the object/class.
+* Added a FieldDefaulter test listeners that set all instance field to their default value after each test method. This listener can be used to automatically set all instances to null after each test method instead of doing so manually in a tearDown method.
+* Added three new methods to the PowerMock API, reset(Object...mocks), reset(Class<?>...classMocks) and resetAll(). The methods can be used to reset instance mocks, class mocks or let PowerMock reset all mocks automatically.
+* mockStaticNice(Class<?> clazz, String... methodNames) was renamed to mockStaticPartialNice in the PowerMock API.
+* PowerMock and PowerMockito now _really_ follows the EasyMock semantics for partial mocking (e.g. PowerMock.createMock(MyClass.class, null) now mocks all methods of a class whereas PowerMock.createMock(MyClass.class, new Method[0]) mocks no methods of a class).
+* The @PrepareForTest annotation now accepts interfaces as types. This is useful in situations where you wan't to make sure that a certain interface is loaded by the same classloader as the rest of the mocks.
+* Updated the tutorial projects to reflect the latest changes in PowerMock.
+* Errors are propagated correctly when invoking the PowerMock.replay(..) method (i.e. they are no longer wrapped in run-time exceptions).
+* Added a MockNice and MockStrict annotation which can be placed on fields to allow for the AnnotationEnabler of the EasyMock api to create and inject mock objects.
+* Changed so that the default suppression value for methods returning java.lang.String is null to conform with EasyMock and Mockito.
+* Added Whitebox.getFieldsOfType(..) that can be used to retreive all fields of a particular type in a class hierarchy.
+* Added support for mock policies. A mock policy can be used to make it easier to unit test some code with PowerMock in isolation from a certain framework. Three mock policies are available in the EasyMock API, JclMockPolicy, Slf4jMockPolicy and Log4jMockPolicy which helps with mocking java commons-lang, log4j or slf4j in PowerMock. Use the @MockPolicy annotation at the class-level of the test case to use one of the mock policies.
+* Whitebox.getMethod(..) sets the accessable flag to true if a method is found.
+* Added Whitebox.getMethod(Class<?> type, Class<?>... parameterTypes) that let's you get a single method without specifying the method name.
+* Fixed a bug in WhiteboxImpl.checkIfTypesAreSame(..) that prevented classes to be identified correctly.
+* Fixed a bug in the PowerMockJUnit44RunnerDelegateImpl that caused a NoClassDefFoundError to be thrown when using JUnit 4.5 when a AssumptionViolatedException was thrown. The reason for this was that JUnit has changed to locatation of this exception.
+* Added spy functionality of final classes and methods to the Mockito API (experimental).
+* Fixed so that it works to place the PrepareForTest annotation at methods without specifying it at the class-level first.
+* Added Whitebox.getField(..) method to get a field somewhere in the hierarchy.
+* Added Whitebox.getFields(..) method to get fields in a class matching a specific name.
+* Added methods to the PowerMock API, PowerMock.suppressField(..), that allows to suppress specific fields of a class (no support for primitive final fields right now).
+* Deprecation: org.powermock.PowerMock and org.powermock.Whitebox have been deprecated, you should now use org.powermock.api.easymock.PowerMock and org.powermock.reflect.Whitebox instead.
+
+Change log 1.0 (released 2008-11-18)
+------------------------------------
+* Changed the pom.xml for the tutorial project so that it's now a stand-alone project.
+* Fixed so that replay all and verify all also works for createMockAndExpectNew.
+* Added method createStrictMockAndExpectNew and createNiceMockAndExpectNew
+* Fixed so that suppressMethodCode returns an empty string for methods returning String.
+* Fixed a bug in the byte-code manipulation of constructors, modifiers that doesn't need change are now preserved.
+* Added the PrepareEverythingForTestAnnotation, this annotation can be used to tell PowerMock to modify all classes.
+* MockGateway doMethodCall now also supports java proxy types.
+* Implemented the ability to set and get internal state based on field type. This means that you get more refactor friendly code while still being able to set or get internal state.
+* Implemented the ability to set internal state based on an object type, i.e. you can now do setInternalState(object, myServiceImpl) to set the first field in object which can be assignable to myServiceImpl. This means that you get more refactor friendly code while still being able to set internal state.
+* Get and setInternalState now separates between class and instance fields, i.e. you cannot set static fields by specifying an instance object.
+* Updated the tutorial projects to take advantage of the latest features in PowerMock.
+* Fixed a NPE bug in the AbstractTestClassExtractor.isPrepared(..) method.
+* The test class is no longer recommended as a PrepareForTest candidate if a NPE occurs inside the test class.
+* Added createStrictPartialMockForAllMethodsExcept and createNicePartialMockForAllMethodsExcept to the PowerMock API.
+* The Whitebox API method getAllMethodExcept now traverses the class hierarchy looking for methods.
+* Fixed a bug in the verifyAll method of the PowerMock API, the state is now properly disposed.
+* Verify now only clears state of the artifact being verified, this means that you use sequential verify statements again. However you must always use a PowerMockRunner in order to make sure that the full state is properly disposed.
+* The suppressConstructorCode method of the PowerMock API was renamed to suppressConstructor.
+* The suppressMethodCode method of the PowerMock API was renamed to suppressMethod.
+* The suppressConstructorCodeHierarchy method of the PowerMock API was removed, suppressConstructor(..) automatically suppress the full hierarchy so use this method instead.
+* Added the PowerMockIgnore annotation that can be used to specify packages or classes that should not be loaded by PowerMock's classloader.
+* Fixed a bug in MockGateway that prevented wrapper/primitive constructors from being correctly executed.
+* Added support for specifying parameter types for expectNew and createMockAndExpectNew, createNiceMockAndExpectNew, createStrictMockAndExpectNew.
+* Added expectNiceNew and expectStrictNew, expectNiceNew can be used with no parameters.
+* Internal refactoring of the chunking mechanism
+* Fixed a bug in the chunking algorithm that made the test listener clear state for all class loaders even though it should only clear the state for the last one. Fixed this for JUnit4 and JUnit3.
+
+Change log 0.9 (released 2008-11-10)
+------------------------------------
+* Structural refactoring to remove Structure 101 XS: moved WhiteBox implementation to separate class in core and moved IndicateReloadClass
+* By default Whitebox.getInternalState and Whitebox.setInternalState now traverses the class hierarchy when looking for a field.
+* Better error message if a NPE is caught in a subclass of a class being prepared for test.
+* The PrepareForTest annotation now manipulates the full (super) class hierachy by default. This makes it easier to perform mocking of super class methods.
+* A new annotation called PrepareOnlyThisForTest has been added and works in the same way that PrepareForTest previously did, i.e. ONLY the specified classes are prepared and not the entire hierarchy.
+* Fixed a bug that made it impossible to invoke vararg constructors.
+* createMockAndExpectNew now takes expected arguments as the second parameter.
+* expectNew takes expected arguments as the second parameter.
+* Invocations of var arg methods, constructors and expectPrivate now works for sub-types of the declared parameter types.
+* More consistent error messages when expectNew fails. Error messages now takes the parameters into account.
+* Renamed mockStaticMethodX to mockStaticPartialX
+* Added javadoc to the release phase
+* The JUnit4 legacy runner now throws NoTestsRemainException if no tests are found in the test case.
+* All JUnit4 runners now executes the setUp method before each test and the tearDown method after each test if the test class extends from TestCase.
+* Fixed an issue in the getAllChunkEntries method of the AbstractTestSuiteChunkerImpl class that caused test methods to be executed in a different order when running in a test suite than running the test stand alone.
+* Fixed a serious issue when the suppress static constructor state disappeared between chunking sessions. Fixed this for all versions of JUnit 4. This means that chunking and suppression of static initializers now work as expected.
+* The PowerMock API methods with a syntax like createPartialMockX are renamed to createXPartialMock, e.g. createPartialMockNice is renamed to createNicePartialMock to be more consistent with the normal createMock methods.
+* Added createNicePartialMockAndInvokeDefaultConstructor and createStrictPartialMockAndInvokeDefaultConstructor to the PowerMock API.
+* Updated the tutorial projects with TODO's. It should now be much easier to understand what shall be done.
+* Changed the clean-up mechanisms of PowerMock.replay(..) and PowerMock.verify(..). Should no longer clear unnecessary state.
+* Implemented two new PowerMock API methods: replayAll and verifyAll(). These can be used to replay and verify all classes and mocks created by the PowerMock API without having to explicitly specify each and everyone.
+
+Change log 0.8.5 (releasd 2008-10-30)
+-------------------------------------
+* Fixed so that it's now possible to mock abstract methods
+* WhiteBox.getMethod(..) now also returns protected and package-private methods.
+* Whitebox.invokeMethod can now execute methods in a super class.
+* Whitebox.invokeMethod no longer throws NullPointerException when an argument is null when the method cannot be found
+* It's is now possible to use sub-types of method parameters when using Whitebox.invokeMethod.
+* Tests methods starting with "test" are now executed only if the method is annotated with @Test or if the test class extends from TestCase.
+* Tests are now executed in the order that they are defined in the test case.
+
+Change log 0.8.1 (released 2008-10-26)
+--------------------------------------
+* Added PowerMock API method "createPartialMockAndInvokeDefaultConstructor" that invokes a default constructor after mock creation (even if it's private).
+* createPartialMock now works as expected
+* Fixed so that it works to mock package private classes (even if they're signed)
+* It now works to set a static final field after the static initializes have been suppressed.
+* Fixed a serious bug that caused classes extending java.lang.Object to be non-mockable.
+
+Change log 0.8 (released 2008-10-22)
+-----------------------------------
+* The junit4 test module now work with JUnit 4.5 (although using the old, now deprecated, approach of JUnit 4.4).
+* Upgraded to EasyMock 2.4
+* Upgraded to JavaAssist 3.8.0.GA
+* WhiteBox invoke method and invoke constructor methods now throws an IllegalArgumentException if the first argument is null.
+* Replay/verify works as expected when mixing classes and instance mocks.
+* Better error message when expectNew fails due to too few calls to new when a method was invoked using reflection.
+* Implemented support for nice mocks.
+* Added more documentation
+* expectNew(..).andThrow(..) now works with checked exceptions
+* Added WhiteBox functionality to instantiate a class without invoking its constructor without using byte-code manipulation. Works in multiple JVM's.
+* mockMethodX is renamed to createPartialMockX
+* Fixed the error message that was thrown when a constructor was not found when using mocks as arguments with createPartialMock.
+* Suppress constructor code now works as expected
+* mockConstruction(..) was removed. You should always use expectNew(..) instead. There's a utility method in PowerMock called createMockAndExpectNew that can be used as a substitute for mockConstruction(..).
+* Better error message when a class is not replayed when doing expectNew.
+* Added support to easy suppress several methods in the same class.
+* doInvokeMethod in PowerMock now catches and deals correctly with InvocationTargetExceptions.
+* It's now possible to run a single test case in junit4
+* Test delegates now implements Sortable
+* Added support for mocking classes in signed jar files
+* EasyMock matchers now works in combination with PowerMock's expectPrivate(..)
+* Added support for invoking var args constructors and methods using Whitebox
+* Added support for expecting private methods with var args parameter
+* PowerMock now supports Hamcrest matchers
+* Exceptions are now propagated correctly from the junit runners.
+
+Change log 0.7 (released)
+-------------------------
+* Do not mock hashCode and equals
+* Added ugly hack for cglib classloading issue with maven
+* Fixed problems with mocking methods in superclass and modifying multiple classes with same parent
+* Strict mocking with interface work as expected
+* Added niceReplayAndVerify
+* Added logo and improved documentation structure
+* Follow EasyMock semantics for partial mocking
+* WhiteBox internalstate support for static fields as expected
+* Updated assembly and create sources jar files
+
+Change log 0.6 (released)
+-------------------------
+* Updated to EasyMock 2.3 and classextension 2.3
+* Implemented support for ConstructorArgs
+* Implemented support for StrictMock
+* Added possibility to invoke a private method in a subclass of an instance using Whitebox.
+* Added a support for test classes extending from TestCase when using a custom JUnit runner such as PowerMockRunner. This fix was created for both JUnit4 legacy and JUnit 4.4.
+* Major internal refactoring.
+* Fixed major classloading and byte-code manipulation issues. Code coverage tools such as EMMA now works.
+* Fixed so that it's now possible to invoke private methods using non-primitive and/or non-wrapper values.
+* Whitebox now throws the correct exceptions to the client and not a wrapped RuntimeException. This means for example that expectNew(..).andThrow(..) works as expected.
+* Fixed a bug in the PowerMock JUnit 4.4 and legacy runner that reported back the wrong number of tests being executed when @Ignore was used.
diff --git a/classloading/classloading-base/pom.xml b/classloading/classloading-base/pom.xml
new file mode 100644
index 0000000..2dde001
--- /dev/null
+++ b/classloading/classloading-base/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-classloading-base</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Utilities for loading and executing classes.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/classloading/classloading-base/src/main/java/org/powermock/classloading/AbstractClassloaderExecutor.java b/classloading/classloading-base/src/main/java/org/powermock/classloading/AbstractClassloaderExecutor.java
new file mode 100644
index 0000000..b487d57
--- /dev/null
+++ b/classloading/classloading-base/src/main/java/org/powermock/classloading/AbstractClassloaderExecutor.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.classloading;
+
+import org.powermock.api.support.ClassLoaderUtil;
+import org.powermock.api.support.SafeExceptionRethrower;
+import org.powermock.classloading.spi.DeepClonerSPI;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.concurrent.Callable;
+
+/**
+ *
+ */
+public abstract class AbstractClassloaderExecutor implements ClassloaderExecutor {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> T execute(Callable<T> callable) {
+ assertArgumentNotNull(callable, "callable");
+ return (T) execute(callable, Whitebox.getMethod(callable.getClass(), "call"));
+ }
+
+ @Override
+ public void execute(Runnable runnable) {
+ assertArgumentNotNull(runnable, "runnable");
+ execute(runnable, Whitebox.getMethod(runnable.getClass(), "run"));
+ }
+
+ private void assertArgumentNotNull(Object object, String argumentName) {
+ if (object == null) {
+ throw new IllegalArgumentException(argumentName + " cannot be null.");
+ }
+ }
+
+ protected abstract Object execute(Object instance, Method method, Object... arguments);
+
+ Object executeWithClassLoader(Object instance, Method method, ClassLoader classloader, Object[] arguments) {
+ final DeepClonerSPI deepCloner = createDeepCloner(classloader);
+ final Object objectLoadedWithClassloader = deepCloner.clone(instance);
+ final Object[] argumentsLoadedByClassLoader = cloneArguments(arguments, deepCloner);
+
+ Object result = getResult(method, objectLoadedWithClassloader, argumentsLoadedByClassLoader);
+
+ return cloneResult(result);
+ }
+
+ private Object cloneResult(Object result) {return result == null ? null : createDeepCloner(getClass().getClassLoader()).clone(result);}
+
+ private Object getResult(Method method, Object objectLoadedWithClassloader, Object[] argumentsLoadedByClassLoader) {
+ Object result = null;
+ try {
+ result = Whitebox.invokeMethod(objectLoadedWithClassloader, method.getName(), argumentsLoadedByClassLoader);
+ } catch (Exception e) {
+ SafeExceptionRethrower.safeRethrow(e);
+ }
+ return result;
+ }
+
+ private Object[] cloneArguments(Object[] arguments, DeepClonerSPI deepCloner) {
+ final Object[] argumentsLoadedByClassLoader = new Object[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ final Object argument = arguments[i];
+ argumentsLoadedByClassLoader[i] = deepCloner.clone(argument);
+ }
+ return argumentsLoadedByClassLoader;
+ }
+
+ private DeepClonerSPI createDeepCloner(ClassLoader classLoader) {
+ final Class<DeepClonerSPI> deepClonerClass = ClassLoaderUtil.loadClass("org.powermock.classloading.DeepCloner");
+ final Constructor<DeepClonerSPI> constructor = Whitebox.getConstructor(deepClonerClass, ClassLoader.class);
+ try {
+ return constructor.newInstance(classLoader);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to instantiate DeepCloner. The DeepCloner implementation must have a one-arg constructor taking a Classloader as parameter.", e);
+ }
+ }
+}
diff --git a/classloading/classloading-base/src/main/java/org/powermock/classloading/ClassloaderExecutor.java b/classloading/classloading-base/src/main/java/org/powermock/classloading/ClassloaderExecutor.java
new file mode 100644
index 0000000..2e3dfca
--- /dev/null
+++ b/classloading/classloading-base/src/main/java/org/powermock/classloading/ClassloaderExecutor.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.classloading;
+
+import java.util.concurrent.Callable;
+
+/**
+ *
+ */
+public interface ClassloaderExecutor {
+
+ <T> T execute(Callable<T> callable);
+
+ void execute(Runnable runnable);
+}
diff --git a/classloading/classloading-base/src/main/java/org/powermock/classloading/SingleClassloaderExecutor.java b/classloading/classloading-base/src/main/java/org/powermock/classloading/SingleClassloaderExecutor.java
new file mode 100644
index 0000000..f4ff9a7
--- /dev/null
+++ b/classloading/classloading-base/src/main/java/org/powermock/classloading/SingleClassloaderExecutor.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.classloading;
+
+import org.powermock.classloading.spi.DeepClonerSPI;
+import org.powermock.classloading.spi.DoNotClone;
+
+import java.lang.reflect.Method;
+
+/**
+ * A ClassLoaderExecutor can run any code in any classloader. E.g. assume you have a classloader
+ * called myClassloader and you want to execute a (void) method called myMethod in myObject using this CL:
+ * <pre>
+ * SingleClassloaderExecutor cle = new SingleClassloaderExecutor(myClassloader);
+ * cle.execute(new Runnable() {
+ * public void run() {
+ * myObject.myMethod();
+ * }
+ * });
+ * </pre>
+ *
+ * What happens is that the entire object graph of myObject is deep-cloned into the <code>myClassloader</code> classloader
+ * and then the <code>myObject.myMethod()</code> is executed.
+ * <p>
+ * You can also execute methods that return something:
+ * <pre>
+ * SingleClassloaderExecutor cle = new SingleClassloaderExecutor(myClassloader);
+ * MyResult result = cle.execute(new Callable<MyResult>() {
+ * public MyResult call() throws Exception {
+ * return myObject.myMethod();
+ * }
+ * });
+ * </pre>
+ * Here we imagine that <code>myObject.myMethod()</code> returns an object of type <code>MyResult</code>. Again the entire
+ * state will be deep-cloned to <code>myClassloader</code> and then the <code>myObject.myMethod()</code> is executed.
+ * The result of the method call is deep-cloned back into the original classloader (the one that made the call to
+ * <code>cle.execute(..)</code>) and is ready for use.
+ * </p>
+ * <p>
+ * Note that the SingleClassloaderExecutor requires a deep cloner implementing the {@link DeepClonerSPI} present in the class-path.
+ * </p>
+ */
+public class SingleClassloaderExecutor extends AbstractClassloaderExecutor {
+
+ @DoNotClone
+ private final ClassLoader classloader;
+
+ public SingleClassloaderExecutor(ClassLoader classloader) {
+ this.classloader = classloader;
+ }
+
+ @Override
+ protected Object execute(Object instance, Method method, Object... arguments) {
+ return executeWithClassLoader(instance, method, classloader, arguments);
+ }
+
+}
diff --git a/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DeepClonerSPI.java b/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DeepClonerSPI.java
new file mode 100644
index 0000000..536b957
--- /dev/null
+++ b/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DeepClonerSPI.java
@@ -0,0 +1,8 @@
+package org.powermock.classloading.spi;
+
+/**
+ * A deep-cloner must implement this interface.
+ */
+public interface DeepClonerSPI {
+ <T> T clone(T objectToClone);
+}
diff --git a/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DoNotClone.java b/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DoNotClone.java
new file mode 100644
index 0000000..eb3db13
--- /dev/null
+++ b/classloading/classloading-base/src/main/java/org/powermock/classloading/spi/DoNotClone.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.classloading.spi;
+
+import java.lang.annotation.*;
+
+/**
+ * Fields annotated with this annotation are not allowed to be cloned by a Deep Cloner implementation.
+ */
+ at Retention(RetentionPolicy.RUNTIME)
+ at Target(ElementType.FIELD)
+ at Inherited
+public @interface DoNotClone {
+}
diff --git a/classloading/classloading-objenesis/pom.xml b/classloading/classloading-objenesis/pom.xml
new file mode 100644
index 0000000..feef7b7
--- /dev/null
+++ b/classloading/classloading-objenesis/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-module</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-classloading-objenesis</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Performs classloader deep-cloning using Objenesis
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/classloading/classloading-objenesis/src/main/java/org/powermock/classloading/DeepCloner.java b/classloading/classloading-objenesis/src/main/java/org/powermock/classloading/DeepCloner.java
new file mode 100644
index 0000000..cf2f251
--- /dev/null
+++ b/classloading/classloading-objenesis/src/main/java/org/powermock/classloading/DeepCloner.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.classloading;
+
+import org.powermock.api.support.ClassLoaderUtil;
+import org.powermock.api.support.SafeExceptionRethrower;
+import org.powermock.classloading.spi.DeepClonerSPI;
+import org.powermock.classloading.spi.DoNotClone;
+import org.powermock.core.ListMap;
+import org.powermock.reflect.Whitebox;
+import sun.misc.Unsafe;
+
+import java.io.*;
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Map;
+
+/**
+ * The purpose of the deep cloner is to create a deep clone of an object. An
+ * object can also be cloned to a different class-loader.
+ * <p>
+ */
+public class DeepCloner implements DeepClonerSPI {
+
+ private final ClassLoader targetCL;
+ private final Map<Object, Object> referenceMap = new ListMap<Object, Object>();
+ private final Class<DoNotClone> doNotClone;
+
+ /**
+ * Clone using the supplied ClassLoader.
+ */
+ public DeepCloner(ClassLoader classLoader) {
+ this.targetCL = classLoader;
+ doNotClone = getDoNotClone(targetCL);
+ }
+
+ /**
+ * Clone using the current ContextClassLoader.
+ */
+ public DeepCloner() {
+ this(Thread.currentThread().getContextClassLoader());
+ }
+
+ private Class<DoNotClone> getDoNotClone(ClassLoader targetCL) {
+ return ClassLoaderUtil.loadClass(DoNotClone.class, targetCL);
+ }
+
+ /**
+ * Clones an object.
+ *
+ * @return A deep clone of the object to clone.
+ */
+ @Override
+ public <T> T clone(T objectToClone) {
+ return clone(objectToClone, true);
+ }
+
+ /**
+ *
+ * @param includeStandardJavaType
+ * <code>true</code> also clones standard java types (using
+ * simple serialization), <code>false</code> simply reference to
+ * these objects (will be same instance).
+ * @return A deep clone of the object to clone.
+ */
+ public <T> T clone(T objectToClone, boolean includeStandardJavaType) {
+ assertObjectNotNull(objectToClone);
+ return performClone(ClassLoaderUtil.loadClass(getType(objectToClone), targetCL), objectToClone,
+ includeStandardJavaType);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> Class<T> getType(T object) {
+ if (object == null) {
+ return null;
+ }
+ return (Class<T>) (object instanceof Class ? object : object.getClass());
+ }
+
+ private static boolean isClass(Object object) {
+ if (object == null) {
+ return false;
+ }
+ return object instanceof Class<?>;
+ }
+
+ private static void assertObjectNotNull(Object object) {
+ if (object == null) {
+ throw new IllegalArgumentException("Object to clone cannot be null");
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> T performClone(Class<T> targetClass, Object source, boolean shouldCloneStandardJavaTypes) {
+ Object target = null;
+ if (targetClass.isArray() && !isClass(source)) {
+ return (T) instantiateArray(targetCL, targetClass, source, shouldCloneStandardJavaTypes);
+ } else if (isJavaReflectMethod(targetClass)) {
+ return (T) cloneJavaReflectMethod(source);
+ } else if (targetClass.isPrimitive() || isSunClass(targetClass) || isJavaReflectClass(targetClass)) {
+ return (T) source;
+ } else if (isSerializableCandidate(targetClass, source)) {
+ return (T) serializationClone(source);
+ } else if (targetClass.isEnum()) {
+ return (T) cloneEnum(targetCL, source);
+ } else if (isClass(source)) {
+ return (T) ClassLoaderUtil.loadClass(getType(source), targetCL);
+ } else {
+ target = isClass(source) ? source : Whitebox.newInstance(targetClass);
+ }
+
+ if (target != null) {
+ referenceMap.put(source, target);
+ cloneFields(targetCL, targetClass, source, target, referenceMap, shouldCloneStandardJavaTypes);
+ }
+ return (T) target;
+ }
+
+ private Object cloneJavaReflectMethod(Object source) {
+ Method sourceMethod = (Method) source;
+ Class<?> declaringClass = sourceMethod.getDeclaringClass();
+ Class<?> targetClassLoadedWithTargetCL = ClassLoaderUtil.loadClass(declaringClass, targetCL);
+ Method targetMethod = null;
+ try {
+ targetMethod = targetClassLoadedWithTargetCL.getDeclaredMethod(sourceMethod.getName(),
+ sourceMethod.getParameterTypes());
+ } catch (Exception e) {
+ SafeExceptionRethrower.safeRethrow(e);
+ }
+ if (sourceMethod.isAccessible()) {
+ targetMethod.setAccessible(true);
+ }
+ return targetMethod;
+ }
+
+ private boolean isJavaReflectMethod(Class<?> cls) {
+ return cls.getName().equals(Method.class.getName());
+ }
+
+ private boolean isSunClass(Class<?> cls) {
+ return cls.getName().startsWith("sun.");
+ }
+
+ private boolean isJavaReflectClass(Class<?> cls) {
+ return cls.getName().startsWith("java.lang.reflect");
+ }
+
+ private <T> boolean isSerializableCandidate(Class<T> targetClass, Object source) {
+ return isStandardJavaType(targetClass)
+ && (isSerializable(targetClass) || isImpliticlySerializable(targetClass))
+ && !Map.class.isAssignableFrom(source.getClass())
+ && !Iterable.class.isAssignableFrom(source.getClass());
+ }
+
+ private static boolean isImpliticlySerializable(Class<?> cls) {
+ return cls.isPrimitive();
+ }
+
+ private static boolean isSerializable(Class<?> cls) {
+ return Serializable.class.isAssignableFrom(cls);
+ }
+
+ /*
+ * Perform simple serialization
+ */
+ private Object serializationClone(Object source) {
+ ObjectOutputStream oos = null;
+ ObjectInputStream ois = null;
+ try {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ oos = new ObjectOutputStream(bos);
+ oos.writeObject(source);
+ oos.flush();
+ ByteArrayInputStream bin = new ByteArrayInputStream(bos.toByteArray());
+ ois = new ObjectInputStream(bin);
+ return ois.readObject();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ close(oos);
+ close(ois);
+ }
+ }
+
+ private void close(Closeable closeable) {
+ try {
+ if (closeable != null) {
+ closeable.close();
+ }
+ } catch (IOException e) {
+ }
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private Object cloneEnum(ClassLoader targetCL, Object source) {
+ Object target;
+ final Class enumClassLoadedByTargetCL = ClassLoaderUtil.loadClass(getType(source), targetCL);
+ target = getEnumValue(source, enumClassLoadedByTargetCL);
+ return target;
+ }
+
+ @SuppressWarnings("unchecked")
+ private <T> void cloneFields(ClassLoader targetCL, Class<T> targetClass, Object source, Object target,
+ Map<Object, Object> referenceMap, boolean cloneStandardJavaTypes) {
+ Class<?> currentTargetClass = targetClass;
+ while (currentTargetClass != null) {
+ for (Field field : currentTargetClass.getDeclaredFields()) {
+ if (field.getAnnotation(doNotClone) != null) {
+ continue;
+ }
+ field.setAccessible(true);
+ try {
+ final Field declaredField = Whitebox.getField(getType(source), field.getName());
+ declaredField.setAccessible(true);
+ final Object object = declaredField.get(source);
+ final Object instantiatedValue;
+ if (object == source) {
+ instantiatedValue = target;
+ } else if (referenceMap.containsKey(object)) {
+ instantiatedValue = referenceMap.get(object);
+ } else {
+ if (object == null && !isIterable(object)) {
+ instantiatedValue = object;
+ } else {
+ Class<Object> type = getType(object);
+ if (type.getName().equals("void")) {
+ type = Class.class.cast(Class.class);
+ }
+ final Class<Object> typeLoadedByCL = ClassLoaderUtil.loadClass(type, targetCL
+ );
+ if (type.isEnum()) {
+ instantiatedValue = getEnumValue(object, typeLoadedByCL);
+ } else {
+ instantiatedValue = performClone(typeLoadedByCL, object, cloneStandardJavaTypes);
+ }
+ }
+ }
+
+ final boolean needsUnsafeWrite = field.isEnumConstant() || isStaticFinalModifier(field);
+ if (needsUnsafeWrite) {
+ UnsafeFieldWriter.write(field, target, instantiatedValue);
+ } else {
+ field.set(target, instantiatedValue);
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ currentTargetClass = currentTargetClass.getSuperclass();
+ }
+ }
+
+ private static <T> boolean isStandardJavaType(Class<T> targetClass) {
+ return targetClass.getName().startsWith("java.");
+ }
+
+ private static boolean isStaticFinalModifier(final Field field) {
+ final int modifiers = field.getModifiers();
+ return Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)
+ || field.getDeclaringClass().equals(Character.class) && field.getName().equals("MIN_RADIX");
+ }
+
+ private static boolean isIterable(final Object object) {
+ return object != null && isIterable(object.getClass());
+ }
+
+ private static boolean isIterable(final Class<?> cls) {
+ return Iterable.class.isAssignableFrom(cls);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ private static Enum getEnumValue(final Object enumValueOfSourceClassloader,
+ final Class<Object> enumTypeLoadedByTargetCL) {
+ return Enum.valueOf((Class) enumTypeLoadedByTargetCL, ((Enum) enumValueOfSourceClassloader).toString());
+ }
+
+ private Object instantiateArray(ClassLoader targetCL, Class<?> arrayClass, Object objectToClone,
+ boolean cloneStandardJavaTypes) {
+ final int arrayLength = Array.getLength(objectToClone);
+ final Object array = Array.newInstance(arrayClass.getComponentType(), arrayLength);
+ for (int i = 0; i < arrayLength; i++) {
+ final Object object = Array.get(objectToClone, i);
+ final Object performClone;
+ if (object == null) {
+ performClone = null;
+ } else {
+ performClone = performClone(ClassLoaderUtil.loadClass(getType(object), targetCL),
+ object, cloneStandardJavaTypes);
+ }
+ Array.set(array, i, performClone);
+ }
+ return array;
+ }
+
+ /**
+ * Most of this code has been copied from the Sun14ReflectionProvider in the
+ * XStream project. Some changes has been made, namely if the field is
+ * static final then the {@link Unsafe#staticFieldOffset(Field)} method is
+ * used instead of {@link Unsafe#objectFieldOffset(Field)}.
+ *
+ * @author Joe Walnes
+ * @author Brian Slesinsky
+ * @author Johan Haleby
+ */
+ private static class UnsafeFieldWriter {
+ private final static Unsafe unsafe;
+ private final static Exception exception;
+ static {
+ Unsafe u = null;
+ Exception ex = null;
+ try {
+ Class<?> objectStreamClass = Class.forName("sun.misc.Unsafe");
+ Field unsafeField = objectStreamClass.getDeclaredField("theUnsafe");
+ unsafeField.setAccessible(true);
+ u = (Unsafe) unsafeField.get(null);
+ } catch (Exception e) {
+ ex = e;
+ }
+ exception = ex;
+ unsafe = u;
+ }
+
+ public static void write(Field field, Object object, Object value) {
+ if (exception != null) {
+ throw new RuntimeException("Could not set field " + object.getClass() + "." + field.getName(),
+ exception);
+ }
+ try {
+ final long offset;
+ if (DeepCloner.isStaticFinalModifier(field)) {
+ offset = unsafe.staticFieldOffset(field);
+ } else {
+ offset = unsafe.objectFieldOffset(field);
+ }
+ Class<?> type = field.getType();
+ if (type.isPrimitive()) {
+ if (type.equals(Integer.TYPE)) {
+ unsafe.putInt(object, offset, ((Integer) value).intValue());
+ } else if (type.equals(Long.TYPE)) {
+ unsafe.putLong(object, offset, ((Long) value).longValue());
+ } else if (type.equals(Short.TYPE)) {
+ unsafe.putShort(object, offset, ((Short) value).shortValue());
+ } else if (type.equals(Character.TYPE)) {
+ unsafe.putChar(object, offset, ((Character) value).charValue());
+ } else if (type.equals(Byte.TYPE)) {
+ unsafe.putByte(object, offset, ((Byte) value).byteValue());
+ } else if (type.equals(Float.TYPE)) {
+ unsafe.putFloat(object, offset, ((Float) value).floatValue());
+ } else if (type.equals(Double.TYPE)) {
+ unsafe.putDouble(object, offset, ((Double) value).doubleValue());
+ } else if (type.equals(Boolean.TYPE)) {
+ unsafe.putBoolean(object, offset, ((Boolean) value).booleanValue());
+ } else {
+ throw new RuntimeException("Could not set field " + object.getClass() + "." + field.getName()
+ + ": Unknown type " + type);
+ }
+ } else {
+ unsafe.putObject(object, offset, value);
+ }
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Could not set field " + object.getClass() + "." + field.getName(), e);
+ }
+ }
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisClassloaderExecutorTest.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisClassloaderExecutorTest.java
new file mode 100644
index 0000000..03ae0e9
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisClassloaderExecutorTest.java
@@ -0,0 +1,303 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading;
+
+import javassist.CtClass;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.powermock.classloading.SingleClassloaderExecutor;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.transformers.MockTransformer;
+import powermock.classloading.classes.MyArgument;
+import powermock.classloading.classes.MyClass;
+import powermock.classloading.classes.MyCollectionHolder;
+import powermock.classloading.classes.MyEnum;
+import powermock.classloading.classes.MyEnumHolder;
+import powermock.classloading.classes.MyHierarchicalFieldHolder;
+import powermock.classloading.classes.MyHierarchicalOverloadedFieldHolder;
+import powermock.classloading.classes.MyIntegerHolder;
+import powermock.classloading.classes.MyPrimitiveArrayHolder;
+import powermock.classloading.classes.MyReferenceFieldHolder;
+import powermock.classloading.classes.MyReturnValue;
+import powermock.classloading.classes.MyStaticFinalArgumentHolder;
+import powermock.classloading.classes.MyStaticFinalNumberHolder;
+import powermock.classloading.classes.MyStaticFinalPrimitiveHolder;
+import powermock.classloading.classes.ReflectionMethodInvoker;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.concurrent.Callable;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+ at Ignore("Since upgrading to JVM 1.6.0_24 lots of tests started to fail")
+public class ObjenesisClassloaderExecutorTest {
+
+ @Test
+ public void loadsObjectGraphInSpecifiedClassloaderAndReturnsResultInOriginalClassloader() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyReturnValue expectedConstructorValue = new MyReturnValue(new MyArgument("first value"));
+ final MyClass myClass = new MyClass(expectedConstructorValue);
+ final MyArgument expected = new MyArgument("A value");
+ MyReturnValue[] actual = new SingleClassloaderExecutor(classloader).execute(new Callable<MyReturnValue[]>() {
+ public MyReturnValue[] call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ return myClass.myMethod(expected);
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+
+ final MyReturnValue myReturnValue = actual[0];
+ assertEquals(expectedConstructorValue.getMyArgument().getValue(), myReturnValue.getMyArgument().getValue());
+ assertEquals(expected.getValue(), actual[1].getMyArgument().getValue());
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesPrimitiveValuesInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final Integer expected = 42;
+ final MyIntegerHolder myClass = new MyIntegerHolder(expected);
+ Integer actual = new SingleClassloaderExecutor(classloader).execute(new Callable<Integer>() {
+ public Integer call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ final int myInteger = myClass.getMyInteger();
+ assertEquals((int) expected, myInteger);
+ return myInteger;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesEnumsInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyEnum expected = MyEnum.MyEnum1;
+ final MyEnumHolder myClass = new MyEnumHolder(expected);
+ MyEnum actual = new SingleClassloaderExecutor(classloader).execute(new Callable<MyEnum>() {
+ public MyEnum call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ MyEnum myEnum = myClass.getMyEnum();
+ assertEquals(expected, myEnum);
+ return myEnum;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void clonesStaticFinalObjectFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalArgumentHolder expected = new MyStaticFinalArgumentHolder();
+ MyStaticFinalArgumentHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalArgumentHolder>() {
+ public MyStaticFinalArgumentHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalArgumentHolder actual = new MyStaticFinalArgumentHolder();
+ assertEquals(expected.getMyObject(), actual.getMyObject());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyObject(), actual.getMyObject());
+ }
+
+ @Test
+ public void clonesStaticFinalPrimitiveFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalPrimitiveHolder expected = new MyStaticFinalPrimitiveHolder();
+ MyStaticFinalPrimitiveHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalPrimitiveHolder>() {
+ public MyStaticFinalPrimitiveHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalPrimitiveHolder actual = new MyStaticFinalPrimitiveHolder();
+ assertEquals(expected.getMyInt(), actual.getMyInt());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyInt(), actual.getMyInt());
+ }
+
+ @Test
+ public void clonesStaticFinalNumberFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalNumberHolder expected = new MyStaticFinalNumberHolder();
+ MyStaticFinalNumberHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalNumberHolder>() {
+ public MyStaticFinalNumberHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalNumberHolder actual = new MyStaticFinalNumberHolder();
+ assertEquals(expected.getMyLong(), actual.getMyLong());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyLong(), actual.getMyLong());
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesPrimitiveArraysInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final int[] expected = new int[] { 1, 2 };
+ final MyPrimitiveArrayHolder myClass = new MyPrimitiveArrayHolder(expected);
+ int[] actual = new SingleClassloaderExecutor(classloader).execute(new Callable<int[]>() {
+ public int[] call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ int[] myArray = myClass.getMyArray();
+ assertArrayEquals(expected, myArray);
+ return myArray;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertArrayEquals(expected, actual);
+ }
+
+ @Ignore("It seems like this test works on certain JVM's and fails on others. WHY!??!")
+ @Test
+ public void loadsObjectGraphThatIncludesCollectionInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final Collection<MyReturnValue> expected = new LinkedList<MyReturnValue>();
+ expected.add(new MyReturnValue(new MyArgument("one")));
+ expected.add(new MyReturnValue(new MyArgument("two")));
+ final MyCollectionHolder myClass = new MyCollectionHolder(expected);
+ Collection<?> actual = new SingleClassloaderExecutor(classloader).execute(new Callable<Collection<?>>() {
+ public Collection<?> call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ Collection<?> myCollection = myClass.getMyCollection();
+ for (Object object : myCollection) {
+ assertEquals(MockClassLoader.class.getName(), object.getClass().getClassLoader().getClass()
+ .getName());
+ }
+ return myCollection;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(2, actual.size());
+ for (Object object : actual) {
+ final String value = ((MyReturnValue) object).getMyArgument().getValue();
+ assertTrue(value.equals("one") || value.equals("two"));
+ }
+ }
+
+ @Test
+ public void usesReferenceCloningWhenTwoFieldsPointToSameInstance() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyReferenceFieldHolder tested = new MyReferenceFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertSame(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ // FIXME: This assertion should work:
+ // assertSame(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ }
+ });
+ }
+
+ @Test
+ public void worksWithObjectHierarchy() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyHierarchicalFieldHolder tested = new MyHierarchicalFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument3(), tested.getMyArgument2());
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument3(), tested.getMyArgument2());
+ }
+ });
+ }
+
+ @Test
+ @Ignore("It seems like this test works on certain JVM's and fails on others. WHY!??!")
+ public void worksWithObjectHierarchyAndOverloadedFields() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyHierarchicalOverloadedFieldHolder tested = new MyHierarchicalOverloadedFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument3());
+ assertSame(tested.getMyArgument3(), MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertNotSame(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertEquals(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument3());
+ assertSame(tested.getMyArgument3(), MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertNotSame(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertEquals(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ }
+ });
+ }
+
+ @Test
+ public void worksWithReflection() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyArgument myArgument = new MyArgument("test");
+ final MyReturnValue instance = new MyReturnValue(myArgument);
+ Method method = instance.getClass().getMethod("getMyArgument");
+ final ReflectionMethodInvoker tested = new ReflectionMethodInvoker(method, instance);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ Object invoke = tested.invoke();
+ assertSame(invoke, myArgument);
+ }
+ });
+ }
+
+ private MockClassLoader createClassloader() {
+ MockClassLoader classloader = new MockClassLoader(new String[] { MyClass.class.getName(),
+ MyArgument.class.getName(), MyReturnValue.class.getName() });
+ MockTransformer mainMockTransformer = new MockTransformer() {
+ public CtClass transform(CtClass clazz) throws Exception {
+ return clazz;
+ }
+ };
+ LinkedList<MockTransformer> linkedList = new LinkedList<MockTransformer>();
+ linkedList.add(mainMockTransformer);
+ classloader.setMockTransformerChain(linkedList);
+ return classloader;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisDeepClonerTest.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisDeepClonerTest.java
new file mode 100644
index 0000000..f13a199
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/ObjenesisDeepClonerTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.classloading.DeepCloner;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+public class ObjenesisDeepClonerTest {
+
+ /**
+ * These tests crashes the JVM on version 1.8
+ */
+ @Before
+ public void onlyRunTestsOnNonJava8Environment() throws Exception {
+ assumeTrue(Float.valueOf(System.getProperty("java.specification.version")) < 1.8f);
+ }
+
+ @Test
+ public void clonesJavaInstances() throws Exception {
+ final URL original = new URL("http://www.powermock.org");
+ URL clone = new DeepCloner().clone(original);
+ assertEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+ @Test
+ public void clonesUnmodifiableLists() throws Exception {
+ final UnmodifiableListExample original = new UnmodifiableListExample();
+ UnmodifiableListExample clone = new DeepCloner().clone(original);
+ assertEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+ @Test
+ public void clonesArraysWithNullValues() throws Exception {
+ Object[] original = new Object[] { "Test", null };
+ Object[] clone = new DeepCloner().clone(original);
+ assertArrayEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+}
+
+class UnmodifiableListExample {
+ private List<NotSerializable> cl = Collections.unmodifiableList(Arrays.asList(new NotSerializable()));
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((cl == null) ? 0 : cl.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ powermock.classloading.UnmodifiableListExample other = (powermock.classloading.UnmodifiableListExample) obj;
+ if (cl == null) {
+ if (other.cl != null)
+ return false;
+ } else if (!cl.equals(other.cl))
+ return false;
+ return true;
+ }
+}
+
+class NotSerializable {
+ private final String state = "Nothing";
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((state == null) ? 0 : state.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ powermock.classloading.NotSerializable other = (powermock.classloading.NotSerializable) obj;
+ if (state == null) {
+ if (other.state != null)
+ return false;
+ } else if (!state.equals(other.state))
+ return false;
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyArgument.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyArgument.java
new file mode 100644
index 0000000..29b3e6d
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyArgument.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyArgument {
+
+ private String value;
+
+ public MyArgument(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MyArgument other = (MyArgument) obj;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "MyArgument [value=" + value + "]";
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyClass.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyClass.java
new file mode 100644
index 0000000..84dda58
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyClass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyClass {
+
+ private final MyReturnValue myReturnValue;
+
+ public MyClass(MyReturnValue myReturnValue) {
+ this.myReturnValue = myReturnValue;
+ }
+
+ public MyReturnValue[] myMethod(MyArgument myArgument) {
+ MyReturnValue[] returnValues = new MyReturnValue[2];
+ returnValues[0] = myReturnValue;
+ returnValues[1] = new MyReturnValue(myArgument);
+ return returnValues;
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyCollectionHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyCollectionHolder.java
new file mode 100644
index 0000000..3dc2064
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyCollectionHolder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+import java.util.Collection;
+
+public class MyCollectionHolder {
+
+ private final Collection<?> myCollection;
+
+ public MyCollectionHolder(Collection<?> collection) {
+ super();
+ myCollection = collection;
+ }
+
+ public Collection<?> getMyCollection() {
+ return myCollection;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnum.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnum.java
new file mode 100644
index 0000000..b79b4d9
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnum.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading.classes;
+
+public enum MyEnum {
+
+ MyEnum1, MyEnum2
+
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnumHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnumHolder.java
new file mode 100644
index 0000000..f32f1cd
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyEnumHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyEnumHolder {
+
+ private final MyEnum myEnum;
+
+ public MyEnumHolder(MyEnum myEnum) {
+ super();
+ this.myEnum = myEnum;
+ }
+
+ public MyEnum getMyEnum() {
+ return myEnum;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java
new file mode 100644
index 0000000..76b8ebf
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyHierarchicalFieldHolder extends MyReferenceFieldHolder {
+ private MyArgument myArgument3 = new MyArgument("testing");
+
+ public MyArgument getMyArgument3() {
+ return myArgument3;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java
new file mode 100644
index 0000000..ae2ff29
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyHierarchicalOverloadedFieldHolder extends MyReferenceFieldHolder {
+ public static final MyArgument MY_ARGUMENT = new MyArgument("testing");
+ private MyArgument myArgument3 = MY_ARGUMENT;
+
+ public MyArgument getMyArgument3() {
+ return myArgument3;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyIntegerHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyIntegerHolder.java
new file mode 100644
index 0000000..962a133
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyIntegerHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyIntegerHolder {
+
+ private final int myInteger;
+
+ public MyIntegerHolder(int myInteger) {
+ super();
+ this.myInteger = myInteger;
+ }
+
+ public int getMyInteger() {
+ return myInteger;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java
new file mode 100644
index 0000000..040bcc6
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyPrimitiveArrayHolder {
+
+ private final int[] myArray;
+
+ public MyPrimitiveArrayHolder(int[] myArray) {
+ super();
+ this.myArray = myArray;
+ }
+
+ public int[] getMyArray() {
+ return myArray;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java
new file mode 100644
index 0000000..09b2655
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyReferenceFieldHolder {
+ public static final MyArgument MY_ARGUMENT = new MyArgument("testing");
+
+ private MyArgument myArgument1 = MY_ARGUMENT;
+ private MyArgument myArgument2 = MY_ARGUMENT;
+
+ public MyArgument getMyArgument1() {
+ return myArgument1;
+ }
+
+ public MyArgument getMyArgument2() {
+ return myArgument2;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReturnValue.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReturnValue.java
new file mode 100644
index 0000000..75806da
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyReturnValue.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyReturnValue {
+ private MyArgument myArgument;
+
+ public MyArgument getMyArgument() {
+ return myArgument;
+ }
+
+ public MyReturnValue(MyArgument myArgument) {
+ this.myArgument = myArgument;
+ }
+
+ @Override
+ public String toString() {
+ return "MyReturnValue [myArgument=" + myArgument + "]";
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java
new file mode 100644
index 0000000..387c1ad
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalArgumentHolder {
+
+ private static final MyArgument myObject = new MyArgument("hello");
+
+ public MyArgument getMyObject() {
+ return myObject;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java
new file mode 100644
index 0000000..50d5c25
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalNumberHolder {
+
+ private static final Long myLong = 1L;
+
+ public Long getMyLong() {
+ return myLong;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java
new file mode 100644
index 0000000..6e7bb13
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalPrimitiveHolder {
+
+ private static final int myInt = 1;
+
+ public int getMyInt() {
+ return myInt;
+ }
+}
diff --git a/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java
new file mode 100644
index 0000000..c0d67a7
--- /dev/null
+++ b/classloading/classloading-objenesis/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+import java.lang.reflect.Method;
+
+public class ReflectionMethodInvoker {
+ private final Method method;
+ private final Object instance;
+
+ public ReflectionMethodInvoker(Method method, Object instance) {
+ this.method = method;
+ this.instance = instance;
+ }
+
+ public Object invoke() {
+ try {
+ return method.invoke(instance);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/classloading/classloading-xstream/pom.xml b/classloading/classloading-xstream/pom.xml
new file mode 100644
index 0000000..596a844
--- /dev/null
+++ b/classloading/classloading-xstream/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-module</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Performs classloader deep-cloning using X-Stream
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/classloading/classloading-xstream/src/main/java/org/powermock/classloading/DeepCloner.java b/classloading/classloading-xstream/src/main/java/org/powermock/classloading/DeepCloner.java
new file mode 100644
index 0000000..1d9be26
--- /dev/null
+++ b/classloading/classloading-xstream/src/main/java/org/powermock/classloading/DeepCloner.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.classloading;
+
+import com.thoughtworks.xstream.XStream;
+import org.powermock.classloading.spi.DeepClonerSPI;
+
+/**
+ * The purpose of the deep cloner is to create a deep clone of an object. An
+ * object can also be cloned to a different class-loader.
+ * <p>
+ */
+public class DeepCloner implements DeepClonerSPI {
+ private final XStream xStream;
+
+ /**
+ * Clone using the supplied ClassLoader.
+ */
+ public DeepCloner(ClassLoader classLoader) {
+ xStream = new XStream();
+ xStream.omitField(SingleClassloaderExecutor.class, "classloader");
+ xStream.setClassLoader(classLoader);
+ }
+
+ /**
+ * Clone using the current ContextClassLoader.
+ */
+ public DeepCloner() {
+ this(Thread.currentThread().getContextClassLoader());
+ }
+
+
+
+ /**
+ * Clones an object.
+ *
+ * @return A deep clone of the object to clone.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> T clone(T objectToClone) {
+ final String serialized = xStream.toXML(objectToClone);
+ return (T) xStream.fromXML(serialized);
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamClassloaderExecutorTest.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamClassloaderExecutorTest.java
new file mode 100644
index 0000000..a65c706
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamClassloaderExecutorTest.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading;
+
+import javassist.CtClass;
+import org.junit.Test;
+import org.powermock.classloading.SingleClassloaderExecutor;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.transformers.MockTransformer;
+import powermock.classloading.classes.MyArgument;
+import powermock.classloading.classes.MyClass;
+import powermock.classloading.classes.MyCollectionHolder;
+import powermock.classloading.classes.MyEnum;
+import powermock.classloading.classes.MyEnumHolder;
+import powermock.classloading.classes.MyHierarchicalFieldHolder;
+import powermock.classloading.classes.MyHierarchicalOverloadedFieldHolder;
+import powermock.classloading.classes.MyIntegerHolder;
+import powermock.classloading.classes.MyPrimitiveArrayHolder;
+import powermock.classloading.classes.MyReferenceFieldHolder;
+import powermock.classloading.classes.MyReturnValue;
+import powermock.classloading.classes.MyStaticFinalArgumentHolder;
+import powermock.classloading.classes.MyStaticFinalNumberHolder;
+import powermock.classloading.classes.MyStaticFinalPrimitiveHolder;
+import powermock.classloading.classes.ReflectionMethodInvoker;
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.concurrent.Callable;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class XStreamClassloaderExecutorTest {
+
+ @Test
+ public void loadsObjectGraphInSpecifiedClassloaderAndReturnsResultInOriginalClassloader() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyReturnValue expectedConstructorValue = new MyReturnValue(new MyArgument("first value"));
+ final MyClass myClass = new MyClass(expectedConstructorValue);
+ final MyArgument expected = new MyArgument("A value");
+ MyReturnValue[] actual = new SingleClassloaderExecutor(classloader).execute(new Callable<MyReturnValue[]>() {
+ public MyReturnValue[] call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ return myClass.myMethod(expected);
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+
+ final MyReturnValue myReturnValue = actual[0];
+ assertEquals(expectedConstructorValue.getMyArgument().getValue(), myReturnValue.getMyArgument().getValue());
+ assertEquals(expected.getValue(), actual[1].getMyArgument().getValue());
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesPrimitiveValuesInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final Integer expected = 42;
+ final MyIntegerHolder myClass = new MyIntegerHolder(expected);
+ Integer actual = new SingleClassloaderExecutor(classloader).execute(new Callable<Integer>() {
+ public Integer call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ final int myInteger = myClass.getMyInteger();
+ assertEquals((int) expected, myInteger);
+ return myInteger;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesEnumsInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyEnum expected = MyEnum.MyEnum1;
+ final MyEnumHolder myClass = new MyEnumHolder(expected);
+ MyEnum actual = new SingleClassloaderExecutor(classloader).execute(new Callable<MyEnum>() {
+ public MyEnum call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ MyEnum myEnum = myClass.getMyEnum();
+ assertEquals(expected, myEnum);
+ return myEnum;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void clonesStaticFinalObjectFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalArgumentHolder expected = new MyStaticFinalArgumentHolder();
+ MyStaticFinalArgumentHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalArgumentHolder>() {
+ public MyStaticFinalArgumentHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalArgumentHolder actual = new MyStaticFinalArgumentHolder();
+ assertEquals(expected.getMyObject(), actual.getMyObject());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyObject(), actual.getMyObject());
+ }
+
+ @Test
+ public void clonesStaticFinalPrimitiveFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalPrimitiveHolder expected = new MyStaticFinalPrimitiveHolder();
+ MyStaticFinalPrimitiveHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalPrimitiveHolder>() {
+ public MyStaticFinalPrimitiveHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalPrimitiveHolder actual = new MyStaticFinalPrimitiveHolder();
+ assertEquals(expected.getMyInt(), actual.getMyInt());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyInt(), actual.getMyInt());
+ }
+
+ @Test
+ public void clonesStaticFinalNumberFields() throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final MyStaticFinalNumberHolder expected = new MyStaticFinalNumberHolder();
+ MyStaticFinalNumberHolder actual = new SingleClassloaderExecutor(classloader)
+ .execute(new Callable<MyStaticFinalNumberHolder>() {
+ public MyStaticFinalNumberHolder call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass()
+ .getName());
+ MyStaticFinalNumberHolder actual = new MyStaticFinalNumberHolder();
+ assertEquals(expected.getMyLong(), actual.getMyLong());
+ return actual;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(expected.getMyLong(), actual.getMyLong());
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesPrimitiveArraysInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ MockClassLoader classloader = createClassloader();
+ final int[] expected = new int[] { 1, 2 };
+ final MyPrimitiveArrayHolder myClass = new MyPrimitiveArrayHolder(expected);
+ int[] actual = new SingleClassloaderExecutor(classloader).execute(new Callable<int[]>() {
+ public int[] call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ int[] myArray = myClass.getMyArray();
+ assertArrayEquals(expected, myArray);
+ return myArray;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertArrayEquals(expected, actual);
+ }
+
+ @Test
+ public void loadsObjectGraphThatIncludesCollectionInSpecifiedClassloaderAndReturnsResultInOriginalClassloader()
+ throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final Collection<MyReturnValue> expected = new LinkedList<MyReturnValue>();
+ expected.add(new MyReturnValue(new MyArgument("one")));
+ expected.add(new MyReturnValue(new MyArgument("two")));
+ final MyCollectionHolder myClass = new MyCollectionHolder(expected);
+ Collection<?> actual = new SingleClassloaderExecutor(classloader).execute(new Callable<Collection<?>>() {
+ public Collection<?> call() throws Exception {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ Collection<?> myCollection = myClass.getMyCollection();
+ for (Object object : myCollection) {
+ assertEquals(MockClassLoader.class.getName(), object.getClass().getClassLoader().getClass()
+ .getName());
+ }
+ return myCollection;
+ }
+ });
+
+ assertFalse(MockClassLoader.class.getName().equals(this.getClass().getClassLoader().getClass().getName()));
+ assertEquals(2, actual.size());
+ for (Object object : actual) {
+ final String value = ((MyReturnValue) object).getMyArgument().getValue();
+ assertTrue(value.equals("one") || value.equals("two"));
+ }
+ }
+
+ @Test
+ public void usesReferenceCloningWhenTwoFieldsPointToSameInstance() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyReferenceFieldHolder tested = new MyReferenceFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertSame(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ // FIXME: This assertion should work:
+ // assertSame(tested.getMyArgument1(), MyReferenceFieldHolder.MY_ARGUMENT);
+ }
+ });
+ }
+
+ @Test
+ public void worksWithObjectHierarchy() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyHierarchicalFieldHolder tested = new MyHierarchicalFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument3(), tested.getMyArgument2());
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument3(), tested.getMyArgument2());
+ }
+ });
+ }
+
+ @Test
+ public void worksWithObjectHierarchyAndOverloadedFields() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyHierarchicalOverloadedFieldHolder tested = new MyHierarchicalOverloadedFieldHolder();
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument3());
+ assertSame(tested.getMyArgument3(), MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertNotSame(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertEquals(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ assertEquals(MockClassLoader.class.getName(), this.getClass().getClassLoader().getClass().getName());
+ assertSame(tested.getMyArgument1(), tested.getMyArgument2());
+ assertEquals(tested.getMyArgument1(), tested.getMyArgument3());
+ // Note: Cannot be same using X-Stream
+ assertEquals(tested.getMyArgument3(), MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertNotSame(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ assertEquals(MyReferenceFieldHolder.MY_ARGUMENT, MyHierarchicalOverloadedFieldHolder.MY_ARGUMENT);
+ }
+ });
+ }
+
+ @Test
+ public void worksWithReflection() throws Exception {
+ final MockClassLoader classloader = createClassloader();
+ final MyArgument myArgument = new MyArgument("test");
+ final MyReturnValue instance = new MyReturnValue(myArgument);
+ Method method = instance.getClass().getMethod("getMyArgument");
+ final ReflectionMethodInvoker tested = new ReflectionMethodInvoker(method, instance);
+ new SingleClassloaderExecutor(classloader).execute(new Runnable() {
+ public void run() {
+ Object invoke = tested.invoke();
+ assertSame(invoke, myArgument);
+ }
+ });
+ }
+
+ private MockClassLoader createClassloader() {
+ MockClassLoader classloader = new MockClassLoader(new String[] { MyClass.class.getName(),
+ MyArgument.class.getName(), MyReturnValue.class.getName() });
+ MockTransformer mainMockTransformer = new MockTransformer() {
+ public CtClass transform(CtClass clazz) throws Exception {
+ return clazz;
+ }
+ };
+ LinkedList<MockTransformer> linkedList = new LinkedList<MockTransformer>();
+ linkedList.add(mainMockTransformer);
+ classloader.setMockTransformerChain(linkedList);
+ return classloader;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamDeepClonerTest.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamDeepClonerTest.java
new file mode 100644
index 0000000..49265f6
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/XStreamDeepClonerTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading;
+
+import org.junit.Test;
+import org.powermock.classloading.DeepCloner;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.*;
+
+public class XStreamDeepClonerTest {
+
+ @Test
+ public void clonesJavaInstances() throws Exception {
+ final URL original = new URL("http://www.powermock.org");
+ URL clone = new DeepCloner().clone(original);
+ assertEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+ @Test
+ public void clonesUnmodifiableLists() throws Exception {
+ final UnmodifiableListExample original = new UnmodifiableListExample();
+ UnmodifiableListExample clone = new DeepCloner().clone(original);
+ assertEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+ @Test
+ public void clonesArraysWithNullValues() throws Exception {
+ Object[] original = new Object[] { "Test", null };
+ Object[] clone = new DeepCloner().clone(original);
+ assertArrayEquals(clone, original);
+ assertNotSame(clone, original);
+ }
+
+}
+
+class UnmodifiableListExample {
+ private List<NotSerializable> cl = Collections.unmodifiableList(Arrays.asList(new NotSerializable()));
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((cl == null) ? 0 : cl.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ powermock.classloading.UnmodifiableListExample other = (powermock.classloading.UnmodifiableListExample) obj;
+ if (cl == null) {
+ if (other.cl != null)
+ return false;
+ } else if (!cl.equals(other.cl))
+ return false;
+ return true;
+ }
+}
+
+class NotSerializable {
+ private final String state = "Nothing";
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((state == null) ? 0 : state.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ powermock.classloading.NotSerializable other = (powermock.classloading.NotSerializable) obj;
+ if (state == null) {
+ if (other.state != null)
+ return false;
+ } else if (!state.equals(other.state))
+ return false;
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyArgument.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyArgument.java
new file mode 100644
index 0000000..29b3e6d
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyArgument.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyArgument {
+
+ private String value;
+
+ public MyArgument(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ MyArgument other = (MyArgument) obj;
+ if (value == null) {
+ if (other.value != null)
+ return false;
+ } else if (!value.equals(other.value))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "MyArgument [value=" + value + "]";
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyClass.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyClass.java
new file mode 100644
index 0000000..84dda58
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyClass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyClass {
+
+ private final MyReturnValue myReturnValue;
+
+ public MyClass(MyReturnValue myReturnValue) {
+ this.myReturnValue = myReturnValue;
+ }
+
+ public MyReturnValue[] myMethod(MyArgument myArgument) {
+ MyReturnValue[] returnValues = new MyReturnValue[2];
+ returnValues[0] = myReturnValue;
+ returnValues[1] = new MyReturnValue(myArgument);
+ return returnValues;
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyCollectionHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyCollectionHolder.java
new file mode 100644
index 0000000..3dc2064
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyCollectionHolder.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+import java.util.Collection;
+
+public class MyCollectionHolder {
+
+ private final Collection<?> myCollection;
+
+ public MyCollectionHolder(Collection<?> collection) {
+ super();
+ myCollection = collection;
+ }
+
+ public Collection<?> getMyCollection() {
+ return myCollection;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnum.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnum.java
new file mode 100644
index 0000000..b79b4d9
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnum.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.classloading.classes;
+
+public enum MyEnum {
+
+ MyEnum1, MyEnum2
+
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnumHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnumHolder.java
new file mode 100644
index 0000000..f32f1cd
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyEnumHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyEnumHolder {
+
+ private final MyEnum myEnum;
+
+ public MyEnumHolder(MyEnum myEnum) {
+ super();
+ this.myEnum = myEnum;
+ }
+
+ public MyEnum getMyEnum() {
+ return myEnum;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java
new file mode 100644
index 0000000..76b8ebf
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalFieldHolder.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyHierarchicalFieldHolder extends MyReferenceFieldHolder {
+ private MyArgument myArgument3 = new MyArgument("testing");
+
+ public MyArgument getMyArgument3() {
+ return myArgument3;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java
new file mode 100644
index 0000000..ae2ff29
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyHierarchicalOverloadedFieldHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyHierarchicalOverloadedFieldHolder extends MyReferenceFieldHolder {
+ public static final MyArgument MY_ARGUMENT = new MyArgument("testing");
+ private MyArgument myArgument3 = MY_ARGUMENT;
+
+ public MyArgument getMyArgument3() {
+ return myArgument3;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyIntegerHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyIntegerHolder.java
new file mode 100644
index 0000000..962a133
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyIntegerHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyIntegerHolder {
+
+ private final int myInteger;
+
+ public MyIntegerHolder(int myInteger) {
+ super();
+ this.myInteger = myInteger;
+ }
+
+ public int getMyInteger() {
+ return myInteger;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java
new file mode 100644
index 0000000..040bcc6
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyPrimitiveArrayHolder.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyPrimitiveArrayHolder {
+
+ private final int[] myArray;
+
+ public MyPrimitiveArrayHolder(int[] myArray) {
+ super();
+ this.myArray = myArray;
+ }
+
+ public int[] getMyArray() {
+ return myArray;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java
new file mode 100644
index 0000000..09b2655
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReferenceFieldHolder.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyReferenceFieldHolder {
+ public static final MyArgument MY_ARGUMENT = new MyArgument("testing");
+
+ private MyArgument myArgument1 = MY_ARGUMENT;
+ private MyArgument myArgument2 = MY_ARGUMENT;
+
+ public MyArgument getMyArgument1() {
+ return myArgument1;
+ }
+
+ public MyArgument getMyArgument2() {
+ return myArgument2;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReturnValue.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReturnValue.java
new file mode 100644
index 0000000..75806da
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyReturnValue.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyReturnValue {
+ private MyArgument myArgument;
+
+ public MyArgument getMyArgument() {
+ return myArgument;
+ }
+
+ public MyReturnValue(MyArgument myArgument) {
+ this.myArgument = myArgument;
+ }
+
+ @Override
+ public String toString() {
+ return "MyReturnValue [myArgument=" + myArgument + "]";
+ }
+}
\ No newline at end of file
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java
new file mode 100644
index 0000000..387c1ad
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalArgumentHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalArgumentHolder {
+
+ private static final MyArgument myObject = new MyArgument("hello");
+
+ public MyArgument getMyObject() {
+ return myObject;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java
new file mode 100644
index 0000000..50d5c25
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalNumberHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalNumberHolder {
+
+ private static final Long myLong = 1L;
+
+ public Long getMyLong() {
+ return myLong;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java
new file mode 100644
index 0000000..6e7bb13
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/MyStaticFinalPrimitiveHolder.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+public class MyStaticFinalPrimitiveHolder {
+
+ private static final int myInt = 1;
+
+ public int getMyInt() {
+ return myInt;
+ }
+}
diff --git a/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java
new file mode 100644
index 0000000..c0d67a7
--- /dev/null
+++ b/classloading/classloading-xstream/src/test/java/powermock/classloading/classes/ReflectionMethodInvoker.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.classloading.classes;
+
+import java.lang.reflect.Method;
+
+public class ReflectionMethodInvoker {
+ private final Method method;
+ private final Object instance;
+
+ public ReflectionMethodInvoker(Method method, Object instance) {
+ this.method = method;
+ this.instance = instance;
+ }
+
+ public Object invoke() {
+ try {
+ return method.invoke(instance);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+}
diff --git a/classloading/pom.xml b/classloading/pom.xml
new file mode 100644
index 0000000..5c45721
--- /dev/null
+++ b/classloading/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-classloading-module</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock Classloading Module
+ </description>
+
+ <modules>
+ <module>classloading-base</module>
+ <module>classloading-objenesis</module>
+ <module>classloading-xstream</module>
+ </modules>
+</project>
diff --git a/core/pom.xml b/core/pom.xml
new file mode 100644
index 0000000..9a0f5cf
--- /dev/null
+++ b/core/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2011 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-core</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock core functionality.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/src/main/java/org/powermock/core/ClassLocator.java b/core/src/main/java/org/powermock/core/ClassLocator.java
new file mode 100644
index 0000000..75f80f8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/ClassLocator.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+public class ClassLocator extends SecurityManager {
+ public static Class getCallerClass() {
+ return new ClassLocator().getClassContext()[4];
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/powermock/core/ClassReplicaCreator.java b/core/src/main/java/org/powermock/core/ClassReplicaCreator.java
new file mode 100644
index 0000000..d5cce3f
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/ClassReplicaCreator.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import javassist.*;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class takes care of creating a replica of a class. The class structure
+ * is copied to the new class. This is useful in situations where you want to
+ * create a mock for a class but it's not possible because of some restrictions
+ * (such as the class being loaded by the bootstrap class-loader).
+ */
+public class ClassReplicaCreator {
+
+ private static final String POWERMOCK_INSTANCE_DELEGATOR_FIELD_NAME = "powerMockInstanceDelegatorField";
+ // Used to make each new replica class of a specific type unique.
+ private static AtomicInteger counter = new AtomicInteger(0);
+
+ public Class<?> createClassReplica(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz cannot be null");
+ }
+ ClassPool classpool = ClassPool.getDefault();
+ final String originalClassName = clazz.getName();
+ CtClass originalClassAsCtClass;
+ final CtClass newClass = classpool.makeClass(generateReplicaClassName(clazz));
+ try {
+ originalClassAsCtClass = classpool.get(originalClassName);
+ CtMethod[] declaredMethods = originalClassAsCtClass.getDeclaredMethods();
+ for (CtMethod ctMethod : declaredMethods) {
+ final String code = getReplicaMethodDelegationCode(clazz, ctMethod, null);
+ CtNewMethod.make(ctMethod.getReturnType(), ctMethod.getName(), ctMethod.getParameterTypes(), ctMethod.getExceptionTypes(),
+ code, newClass);
+ }
+
+ return newClass.toClass(this.getClass().getClassLoader(), this.getClass().getProtectionDomain());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Create a class that is a replica of type <code>T</code>. To allow for
+ * partial mocking all calls to non-mocked methods will be delegated to the
+ * <code>delegator</code>.
+ *
+ * @param <T> The type of the replica class to be created.
+ * @param delegator The delegator object that will be invoked to allow for partial
+ * mocking.
+ * @return A replica class that can be used to duck-type an instance.
+ */
+ @SuppressWarnings("unchecked")
+ public <T> Class<T> createInstanceReplica(T delegator) {
+ if (delegator == null) {
+ throw new IllegalArgumentException("delegator cannot be null");
+ }
+ final Class<T> clazz = (Class<T>) delegator.getClass();
+ ClassPool classpool = ClassPool.getDefault();
+ final String originalClassName = clazz.getName();
+ CtClass originalClassAsCtClass;
+ final CtClass newClass = classpool.makeClass(generateReplicaClassName(clazz));
+ try {
+ originalClassAsCtClass = classpool.get(originalClassName);
+
+ copyFields(originalClassAsCtClass, newClass);
+ addDelegatorField(delegator, newClass);
+
+ CtMethod[] declaredMethods = originalClassAsCtClass.getDeclaredMethods();
+ for (CtMethod ctMethod : declaredMethods) {
+ @SuppressWarnings("unused")
+ final String code = getReplicaMethodDelegationCode(delegator.getClass(), ctMethod, POWERMOCK_INSTANCE_DELEGATOR_FIELD_NAME);
+ CtMethod make2 = CtNewMethod.copy(ctMethod, newClass, null);
+ newClass.addMethod(make2);
+ }
+
+ CtConstructor[] declaredConstructors = originalClassAsCtClass.getDeclaredConstructors();
+ for (CtConstructor ctConstructor : declaredConstructors) {
+ CtConstructor copy = CtNewConstructor.copy(ctConstructor, newClass, null);
+ newClass.addConstructor(copy);
+ }
+ return newClass.toClass(this.getClass().getClassLoader(), this.getClass().getProtectionDomain());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Add a field to the replica class that holds the instance delegator. I.e.
+ * if we're creating a instance replica of <code>java.lang.Long</code> this
+ * methods adds a new field of type <code>delegator.getClass()</code> to the
+ * replica class.
+ */
+ private <T> void addDelegatorField(T delegator, final CtClass replicaClass) throws CannotCompileException {
+ CtField f = CtField.make(String.format("private %s %s = null;", delegator.getClass().getName(),
+ POWERMOCK_INSTANCE_DELEGATOR_FIELD_NAME), replicaClass);
+ replicaClass.addField(f);
+ }
+
+ private <T> String generateReplicaClassName(final Class<T> clazz) {
+ return "replica." + clazz.getName() + "$$PowerMock" + counter.getAndIncrement();
+ }
+
+ private void copyFields(CtClass originalClassAsCtClass, final CtClass newClass) throws CannotCompileException, NotFoundException {
+ CtField[] declaredFields = originalClassAsCtClass.getDeclaredFields();
+ CtField[] undeclaredFields = originalClassAsCtClass.getFields();
+ Set<CtField> allFields = new HashSet<CtField>();
+ Collections.addAll(allFields, declaredFields);
+ Collections.addAll(allFields, undeclaredFields);
+
+ for (CtField ctField : allFields) {
+ CtField f = new CtField(ctField.getType(), ctField.getName(), newClass);
+ newClass.addField(f);
+ }
+ }
+
+ /*
+ * Invokes a instance method of the original instance. This enables partial
+ * mocking of system classes.
+ */
+ private String getReplicaMethodDelegationCode(Class<?> clazz, CtMethod ctMethod, String classOrInstanceToDelegateTo)
+ throws NotFoundException {
+ StringBuilder builder = new StringBuilder();
+ builder.append("{java.lang.reflect.Method originalMethod = ");
+ builder.append(clazz.getName());
+ builder.append(".class.getDeclaredMethod(\"");
+ builder.append(ctMethod.getName());
+ builder.append("\", ");
+ final String parametersAsString = getParametersAsString(getParameterTypes(ctMethod));
+ if ("".equals(parametersAsString)) {
+ builder.append("null");
+ } else {
+ builder.append(parametersAsString);
+ }
+ builder.append(");\n");
+ builder.append("originalMethod.setAccessible(true);\n");
+ final CtClass returnType = ctMethod.getReturnType();
+ final boolean isVoid = returnType.equals(CtClass.voidType);
+ if (!isVoid) {
+ builder.append("return (");
+ builder.append(returnType.getName());
+ builder.append(") ");
+ }
+ builder.append("originalMethod.invoke(");
+ if (Modifier.isStatic(ctMethod.getModifiers()) || classOrInstanceToDelegateTo == null) {
+ builder.append(clazz.getName());
+ builder.append(".class");
+ } else {
+ builder.append(classOrInstanceToDelegateTo);
+ }
+ builder.append(", $args);}");
+ return builder.toString();
+ }
+
+ private String[] getParameterTypes(CtMethod ctMethod) throws NotFoundException {
+ final CtClass[] parameterTypesAsCtClass = ctMethod.getParameterTypes();
+ final String[] parameterTypes = new String[parameterTypesAsCtClass.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ parameterTypes[i] = parameterTypesAsCtClass[i].getName() + ".class";
+ }
+ return parameterTypes;
+ }
+
+ private static String getParametersAsString(String[] types) {
+ StringBuilder parametersAsString = new StringBuilder();
+ if (types != null && types.length == 0) {
+ parametersAsString.append("new Class[0]");
+ } else {
+ parametersAsString.append("new Class[] {");
+ if (types != null) {
+ for (int i = 0; i < types.length; i++) {
+ parametersAsString.append(types[i]);
+ if (i != types.length - 1) {
+ parametersAsString.append(", ");
+ }
+ }
+ }
+ parametersAsString.append("}");
+ }
+ return parametersAsString.toString();
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/ConcreteClassGenerator.java b/core/src/main/java/org/powermock/core/ConcreteClassGenerator.java
new file mode 100644
index 0000000..dee07d4
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/ConcreteClassGenerator.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import javassist.*;
+import org.powermock.reflect.internal.TypeUtils;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class takes care of creating a concrete sub-class implementing all
+ * abstract methods in the parent.
+ */
+public class ConcreteClassGenerator {
+
+ // Used to make each new subclass of a specific type unique.
+ private static AtomicInteger counter = new AtomicInteger(0);
+
+ public Class<?> createConcreteSubClass(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("clazz cannot be null");
+ }
+ if (!java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) {
+ throw new IllegalArgumentException("clazz must be abstract");
+ }
+ ClassPool classpool = ClassPool.getDefault();
+ final String originalClassName = clazz.getName();
+ CtClass originalClassAsCtClass = null;
+ final CtClass newClass = classpool.makeClass(generateClassName(clazz));
+ try {
+ newClass.setSuperclass(classpool.get(clazz.getName()));
+ } catch (Exception e1) {
+ throw new RuntimeException(e1);
+ }
+ try {
+ originalClassAsCtClass = classpool.get(originalClassName);
+ CtMethod[] declaredMethods = originalClassAsCtClass.getDeclaredMethods();
+ for (CtMethod ctMethod : declaredMethods) {
+ if (Modifier.isAbstract(ctMethod.getModifiers())) {
+ final String code = getReturnCode(ctMethod.getReturnType());
+ CtNewMethod.make(ctMethod.getReturnType(), ctMethod.getName(), ctMethod.getParameterTypes(),
+ ctMethod.getExceptionTypes(), code, newClass);
+ }
+ }
+ if (!hasInheritableConstructor(originalClassAsCtClass)) {
+ return null;
+ }
+ return newClass.toClass(this.getClass().getClassLoader(), this.getClass().getProtectionDomain());
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private boolean hasInheritableConstructor(CtClass cls) throws NotFoundException {
+ CtConstructor[] constructors = cls.getDeclaredConstructors();
+ if (constructors.length == 0) {
+ return true;
+ }
+ for (CtConstructor ctConstructor : constructors) {
+ int modifiers = ctConstructor.getModifiers();
+ if (!Modifier.isPackage(modifiers) && !Modifier.isPrivate(modifiers)) {
+ return true;
+ }
+ }
+ return false;
+
+ }
+
+ private String getReturnCode(CtClass returnType) {
+ if (returnType.equals(CtClass.voidType)) {
+ return "{}";
+ }
+ return "{return " + TypeUtils.getDefaultValueAsString(returnType.getName()) + ";}";
+ }
+
+ private <T> String generateClassName(final Class<T> clazz) {
+ return "subclass." + clazz.getName() + "$$PowerMock" + counter.getAndIncrement();
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/DefaultFieldValueGenerator.java b/core/src/main/java/org/powermock/core/DefaultFieldValueGenerator.java
new file mode 100644
index 0000000..9f277f1
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/DefaultFieldValueGenerator.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.TypeUtils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.Inet4Address;
+import java.net.InetAddress;
+import java.util.Set;
+
+/**
+ * Fills the fields with default not-null values. If a field type is an
+ * interface a proxy returning default values for each method will be created.
+ * If it's an abstract class a new concrete implementation of that type will
+ * created and instantiated at run-time.
+ * <p>
+ * There are two scenarios where a field-type cannot possibly be assigned.
+ * <ol>
+ * <li>
+ * When a class contains a field of it's own type, which would lead to infinite
+ * recursion, <code>null</code> is assigned.</li>
+ * <li>When the field type is an abstract Java system class with no visible
+ * constructor (package-private) <code>null</code> is assigned.</li>
+ * </ol>
+ */
+public class DefaultFieldValueGenerator {
+
+ public static <T> T fillWithDefaultValues(T object) {
+ if (object == null) {
+ throw new IllegalArgumentException("object to fill cannot be null");
+ }
+ Set<Field> allInstanceFields = Whitebox.getAllInstanceFields(object);
+ for (Field field : allInstanceFields) {
+ final Class<?> fieldType = field.getType();
+ Object defaultValue = TypeUtils.getDefaultValue(fieldType);
+ if (defaultValue == null && fieldType != object.getClass() && !field.isSynthetic()) {
+ defaultValue = instantiateFieldType(field);
+ if (defaultValue != null) {
+ fillWithDefaultValues(defaultValue);
+ }
+ }
+ try {
+ field.set(object, defaultValue);
+ } catch (Exception e) {
+ throw new RuntimeException("Internal error: Failed to set field.", e);
+ }
+ }
+ return object;
+ }
+
+ private static Object instantiateFieldType(Field field) {
+ Class<?> fieldType = field.getType();
+ Object defaultValue;
+ int modifiers = fieldType.getModifiers();
+ if(fieldType.isAssignableFrom(ClassLoader.class) || isClass(fieldType)) {
+ defaultValue = null;
+ } else if (Modifier.isAbstract(modifiers) && !Modifier.isInterface(modifiers) && !fieldType.isArray()) {
+ Class<?> createConcreteSubClass = new ConcreteClassGenerator().createConcreteSubClass(fieldType);
+ defaultValue = createConcreteSubClass == null ? null : Whitebox.newInstance(createConcreteSubClass);
+ } else {
+ fieldType = substituteKnownProblemTypes(fieldType);
+ defaultValue = Whitebox.newInstance(fieldType);
+ }
+ return defaultValue;
+ }
+
+ private static boolean isClass(Class<?> fieldType) {
+ return fieldType == Class.class;
+ }
+
+ /**
+ * Substitute class types that are known to cause problems when generating
+ * them.
+ *
+ * @param fieldType
+ * @return A field-type substitute or the original class.
+ */
+ private static Class<?> substituteKnownProblemTypes(Class<?> fieldType) {
+ /*
+ * InetAddress has a private constructor and is normally not
+ * constructable without reflection. It's no problem instantiating this
+ * class using reflection or with Whitebox#newInstance but the problem
+ * lies in the equals method since it _always_ returns false even though
+ * it's the same instance! So in cases where classes containing an
+ * InetAddress field and uses it in the equals method (such as
+ * java.net.URL) then may return false since InetAddress#equals()
+ * returns false all the time. As a work-around we return an
+ * Inet4Address instead which has a proper equals method.
+ */
+ if (fieldType == InetAddress.class) {
+ return Inet4Address.class;
+ }
+ return fieldType;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/IdentityHashSet.java b/core/src/main/java/org/powermock/core/IdentityHashSet.java
new file mode 100644
index 0000000..1610d35
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/IdentityHashSet.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Map;
+
+public class IdentityHashSet<E> extends AbstractSet<E> {
+
+ protected final Map<E, Boolean> backedMap;
+
+ public IdentityHashSet() {
+ this.backedMap = new ListMap<E, Boolean>();
+ }
+
+ @Override
+ public int size() {
+ return backedMap.size();
+ }
+
+ @Override
+ public boolean contains(Object o) {
+ return backedMap.containsKey(o);
+ }
+
+ @Override
+ public boolean add(E o) {
+ return backedMap.put(o, Boolean.TRUE) == null;
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return backedMap.keySet().iterator();
+ }
+
+ @Override
+ public boolean remove(Object o) {
+ return backedMap.remove(o) != null;
+ }
+
+ @Override
+ public void clear() {
+ backedMap.clear();
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/IndicateReloadClass.java b/core/src/main/java/org/powermock/core/IndicateReloadClass.java
new file mode 100644
index 0000000..7f0f39b
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/IndicateReloadClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+public class IndicateReloadClass {
+
+}
diff --git a/core/src/main/java/org/powermock/core/ListMap.java b/core/src/main/java/org/powermock/core/ListMap.java
new file mode 100644
index 0000000..756a49d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/ListMap.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import java.util.*;
+
+public class ListMap<K, V> implements Map<K, V> {
+
+ private List<Map.Entry<K, V>> entries = new LinkedList<Entry<K, V>>();
+
+ private static class SimpleEntry<K, V> implements Entry<K, V> {
+
+ private K key;
+ private V value;
+
+ public SimpleEntry(K key, V value) {
+ this.key = key;
+ this.value = value;
+ }
+
+ @Override
+ public K getKey() {
+ return key;
+ }
+
+ @Override
+ public V getValue() {
+ return value;
+ }
+
+ @Override
+ public V setValue(V value) {
+ V old = this.value;
+ this.value = value;
+ return old;
+ }
+
+ };
+
+ @Override
+ public V remove(Object key) {
+ for (Iterator<Map.Entry<K, V>> i = entries.iterator(); i.hasNext();) {
+ Map.Entry<K, V> entry = i.next();
+ if (entry.getKey() == key) {
+ i.remove();
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void clear() {
+ entries.clear();
+ }
+
+ @Override
+ public V get(Object key) {
+ for (Iterator<Map.Entry<K, V>> i = entries.iterator(); i.hasNext();) {
+ Map.Entry<K, V> entry = i.next();
+ if (entry.getKey() == key) {
+ return entry.getValue();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public V put(K key, V value) {
+ for (Iterator<Map.Entry<K, V>> i = entries.iterator(); i.hasNext();) {
+ Map.Entry<K, V> entry = i.next();
+ if (entry.getKey() == key) {
+ return entry.setValue(value);
+ }
+ }
+ Map.Entry<K, V> entry = new SimpleEntry<K, V>(key, value);
+ entries.add(entry);
+ return null;
+ }
+
+ @Override
+ public boolean containsKey(Object key) {
+ return get(key) != null;
+ }
+
+ @Override
+ public boolean containsValue(Object value) {
+ for (Iterator<Map.Entry<K, V>> i = entries.iterator(); i.hasNext();) {
+ Map.Entry<K, V> entry = i.next();
+ if (entry.getValue() == value) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<K, V>> entrySet() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return entries.isEmpty();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ Set<K> identityHashSet = new HashSet<K>();
+ for (Map.Entry<K, V> entry : entries) {
+ identityHashSet.add(entry.getKey());
+ }
+ return identityHashSet;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void putAll(Map<? extends K, ? extends V> t) {
+ Set<?> entrySet = t.entrySet();
+ for (Object object : entrySet) {
+ entries.add((java.util.Map.Entry<K, V>) object);
+ }
+ }
+
+ @Override
+ public int size() {
+ return entries.size();
+ }
+
+ @Override
+ public Collection<V> values() {
+ Set<V> hashSet = new HashSet<V>();
+ for (Map.Entry<K, V> entry : entries) {
+ hashSet.add(entry.getValue());
+ }
+ return hashSet;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/MockGateway.java b/core/src/main/java/org/powermock/core/MockGateway.java
new file mode 100644
index 0000000..dd20eed
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/MockGateway.java
@@ -0,0 +1,274 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.core.spi.NewInvocationControl;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.internal.TypeUtils;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * All mock invocations are routed through this gateway. This includes method
+ * calls, construction of new instances and more. Do not use this class
+ * directly, but always go through the PowerMock facade.
+ */
+public class MockGateway {
+
+ public static final Object PROCEED = new Object();
+ public static final Object SUPPRESS = new Object();
+
+
+ /**
+ * Used to tell the MockGateway that the next call should not be mocked
+ * regardless if a {@link MethodInvocationControl} is found in the
+ * {@link MockRepository}. Used to allow for e.g. recursive partial mocking.
+ */
+ public static final String DONT_MOCK_NEXT_CALL = "DontMockNextCall";
+
+ /**
+ * Tells PowerMock to mock standard methods. These are
+ * {@link Object#toString()}, {@link Object#hashCode()} and
+ * {@link Object#equals(Object)}. By default this is <code>true</code>.
+ */
+ public static boolean MOCK_STANDARD_METHODS = true;
+ /**
+ * Tells PowerMock whether or not to mock
+ * {@link java.lang.Object#getClass()}.
+ */
+ public static boolean MOCK_GET_CLASS_METHOD = false;
+
+ // used for static methods
+ @SuppressWarnings("UnusedDeclaration")
+ public static Object methodCall(Class<?> type, String methodName, Object[] args, Class<?>[] sig,
+ String returnTypeAsString) throws Throwable {
+ return doMethodCall(type, methodName, args, sig, returnTypeAsString);
+ }
+
+ private static Object doMethodCall(Object object, String methodName, Object[] args, Class<?>[] sig,
+ String returnTypeAsString) throws Throwable {
+ if (!shouldMockMethod(methodName, sig)) {
+ return PROCEED;
+ }
+ Object returnValue = null;
+
+ MethodInvocationControl methodInvocationControl;
+ Class<?> objectType;
+
+ if (object instanceof Class<?>) {
+ objectType = (Class<?>) object;
+ methodInvocationControl = MockRepository.getStaticMethodInvocationControl(objectType);
+ } else {
+ final Class<?> type = object.getClass();
+ objectType = WhiteboxImpl.getUnmockedType(type);
+ methodInvocationControl = MockRepository.getInstanceMethodInvocationControl(object);
+ }
+
+ /*
+ * if invocationControl is null or the method is not mocked, invoke
+ * original method or suppress the method code otherwise invoke the
+ * invocation handler.
+ */
+ Method method;
+ try {
+ method = WhiteboxImpl.getBestMethodCandidate(objectType, methodName, sig, true);
+ } catch (MethodNotFoundException e) {
+ /*
+ * Dirty hack to get around issue 110
+ * (http://code.google.com/p/powermock/issues/detail?id=110). Review
+ * this! What we do here is to try to find a reflective method on
+ * class. This has begun to fail since version 1.2 when we supported
+ * mocking static methods in system classes.
+ */
+ try {
+ method = WhiteboxImpl.getMethod(Class.class, methodName, sig);
+ } catch (MethodNotFoundException e2) {
+ throw e;
+ }
+ }
+
+ // Fix for Issue http://code.google.com/p/powermock/issues/detail?id=88
+ // For some reason the method call to equals() on final methods is
+ // intercepted and during the further processing in Mockito the same
+ // equals() method is called on the same instance. A StackOverflowError
+ // is the result. The following fix changes this by checking if the
+ // method to be called is a final equals() method. In that case the
+ // original method is called by returning PROCEED.
+ if ( // The following describes the equals method.
+ "equals".equals(method.getName())
+ && method.getParameterTypes().length == 1
+ && method.getParameterTypes()[0] == Object.class
+ && Modifier.isFinal(method.getModifiers())) {
+ returnValue = PROCEED;
+ } else {
+
+ // At first should be checked that method not suppressed/stubbed, because otherwise for spies real
+ // method is involved.
+ // https://github.com/jayway/powermock/issues/327
+
+ if (MockRepository.shouldSuppressMethod(method, objectType)){
+ returnValue = TypeUtils.getDefaultValue(returnTypeAsString);
+ }else if (MockRepository.shouldStubMethod(method)) {
+ returnValue = MockRepository.getMethodToStub(method);
+ } else if (methodInvocationControl != null && methodInvocationControl.isMocked(method) && shouldMockThisCall()) {
+ returnValue = methodInvocationControl.invoke(object, method, args);
+ if (returnValue == SUPPRESS) {
+ returnValue = TypeUtils.getDefaultValue(returnTypeAsString);
+ }
+ } else if (MockRepository.hasMethodProxy(method)) {
+ /*
+ * We must temporary remove the method proxy when invoking the
+ * invocation handler because if the invocation handler delegates
+ * the call we will end up here again and we'll get a
+ * StackOverflowError.
+ */
+ final InvocationHandler invocationHandler = MockRepository.removeMethodProxy(method);
+ try {
+ returnValue = invocationHandler.invoke(object, method, args);
+ } finally {
+ // Set the method proxy again after the invocation
+ MockRepository.putMethodProxy(method, invocationHandler);
+ }
+
+ } else {
+ returnValue = PROCEED;
+ }
+ }
+
+ return returnValue;
+ }
+
+ private static boolean shouldMockMethod(String methodName, Class<?>[] sig) {
+ if (isJavaStandardMethod(methodName, sig) && !MOCK_STANDARD_METHODS) {
+ return false;
+ } else if (isGetClassMethod(methodName, sig) && !MOCK_GET_CLASS_METHOD) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ private static boolean isJavaStandardMethod(String methodName, Class<?>[] sig) {
+ return (methodName.equals("equals") && sig.length == 1) || (methodName.equals("hashCode") && sig.length == 0)
+ || (methodName.equals("toString") && sig.length == 0);
+ }
+
+ private static boolean isGetClassMethod(String methodName, Class<?>[] sig) {
+ return methodName.equals("getClass") && sig.length == 0;
+ }
+
+ private static boolean shouldMockThisCall() {
+ Object shouldSkipMockingOfNextCall = MockRepository.getAdditionalState(DONT_MOCK_NEXT_CALL);
+ final boolean shouldMockThisCall = shouldSkipMockingOfNextCall == null;
+ MockRepository.removeAdditionalState(DONT_MOCK_NEXT_CALL);
+ return shouldMockThisCall;
+ }
+
+ // used for instance methods
+ @SuppressWarnings("UnusedDeclaration")
+ public static Object methodCall(Object instance, String methodName, Object[] args, Class<?>[] sig,
+ String returnTypeAsString) throws Throwable {
+ return doMethodCall(instance, methodName, args, sig, returnTypeAsString);
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public static Object newInstanceCall(Class<?> type, Object[] args, Class<?>[] sig) throws Throwable {
+ final NewInvocationControl<?> newInvocationControl = MockRepository.getNewInstanceControl(type);
+ if (newInvocationControl != null) {
+ /*
+ * We need to deal with inner, local and anonymous inner classes
+ * specifically. For example when new is invoked on an inner class
+ * it seems like null is passed as an argument even though it
+ * shouldn't. We correct this here.
+ *
+ * Seems with Javassist 3.17.1-GA & Java 7, the 'null' is passed as the last argument.
+ */
+ if (type.isMemberClass() && Modifier.isStatic(type.getModifiers())) {
+ if (args.length > 0 && (args[0] == null || args[args.length - 1] == null) && sig.length > 0) {
+ args = copyArgumentsForInnerOrLocalOrAnonymousClass(args, false);
+ }
+ } else if (type.isLocalClass() || type.isAnonymousClass() || type.isMemberClass()) {
+ if (args.length > 0 && sig.length > 0 && sig[0].equals(type.getEnclosingClass())) {
+ args = copyArgumentsForInnerOrLocalOrAnonymousClass(args, true);
+ }
+ }
+ return newInvocationControl.invoke(type, args, sig);
+ }
+ // Check if we should suppress the constructor code
+ if (MockRepository.shouldSuppressConstructor(WhiteboxImpl.getConstructor(type, sig))) {
+ return WhiteboxImpl.getFirstParentConstructor(type);
+ }
+ return PROCEED;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public static Object fieldCall(Object instanceOrClassContainingTheField, Class<?> classDefiningField,
+ String fieldName, Class<?> fieldType) {
+ if (MockRepository.shouldSuppressField(WhiteboxImpl.getField(classDefiningField, fieldName))) {
+ return TypeUtils.getDefaultValue(fieldType);
+ }
+ return PROCEED;
+ }
+
+ public static Object staticConstructorCall(String className) {
+ if (MockRepository.shouldSuppressStaticInitializerFor(className)) {
+ return "suppress";
+ }
+ return PROCEED;
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ public static Object constructorCall(Class<?> type, Object[] args, Class<?>[] sig) throws Throwable {
+ final Constructor<?> constructor = WhiteboxImpl.getConstructor(type, sig);
+ if (MockRepository.shouldSuppressConstructor(constructor)) {
+ return null;
+ }
+ return PROCEED;
+ }
+
+ /**
+ * The first parameter of an inner, local or anonymous inner class is
+ * <code>null</code> or the enclosing instance. This should not be included
+ * in the substitute invocation since it is never expected by the user.
+ * <p/>
+ * Seems with Javassist 3.17.1-GA & Java 7, the '<code>null</code>' is passed as the last argument.
+ */
+ private static Object[] copyArgumentsForInnerOrLocalOrAnonymousClass(Object[] args, boolean excludeEnclosingInstance) {
+ Object[] newArgs = new Object[args.length - 1];
+ final int start;
+ final int end;
+ int j = 0;
+
+ if (args[0] == null || excludeEnclosingInstance) {
+ start = 1;
+ end = args.length;
+ } else {
+ start = 0;
+ end = args.length - 1;
+ }
+
+ for (int i = start; i < end; i++) {
+ newArgs[j++] = args[i];
+ }
+ args = newArgs;
+ return args;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/MockRepository.java b/core/src/main/java/org/powermock/core/MockRepository.java
new file mode 100644
index 0000000..143027d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/MockRepository.java
@@ -0,0 +1,390 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import org.powermock.core.spi.MethodInvocationControl;
+import org.powermock.core.spi.NewInvocationControl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.*;
+
+/**
+ * Hold mock objects that should be used instead of the concrete implementation.
+ * Mock transformers may use this class to gather information on which classes
+ * and methods that are mocked.
+ */
+public class MockRepository {
+
+ private static Set<Object> objectsToAutomaticallyReplayAndVerify = new IdentityHashSet<Object>();
+
+ private static Map<Class<?>, NewInvocationControl<?>> newSubstitutions = new HashMap<Class<?>, NewInvocationControl<?>>();
+
+ /**
+ * Holds info about general method invocation mocks for classes.
+ */
+ private static Map<Class<?>, MethodInvocationControl> classMocks = new HashMap<Class<?>, MethodInvocationControl>();
+
+ /**
+ * Holds info about general method invocation mocks for instances.
+ */
+ private static Map<Object, MethodInvocationControl> instanceMocks = new ListMap<Object, MethodInvocationControl>();
+
+ /**
+ * Holds info about which methods that should return a substitute/another
+ * instance instead of the default instance.
+ */
+ private static Map<Method, Object> substituteReturnValues = new HashMap<Method, Object>();
+
+ /**
+ * Holds info about which methods that are proxied.
+ */
+ private static Map<Method, InvocationHandler> methodProxies = new HashMap<Method, InvocationHandler>();
+
+ /**
+ * Holds info about which class that should have their static initializers
+ * suppressed.
+ */
+ private static Set<String> suppressStaticInitializers = new HashSet<String>();
+
+ /**
+ * Sometimes mock frameworks needs to store additional state. They can do
+ * this using this key/value based approach.
+ */
+ private static Map<String, Object> additionalState = new HashMap<String, Object>();
+
+ /**
+ * Set of constructors that should be suppressed.
+ */
+ private static final Set<Constructor<?>> suppressConstructor = new HashSet<Constructor<?>>();
+
+ /**
+ * Set of methods that should be suppressed.
+ */
+ private static final Set<Method> suppressMethod = new HashSet<Method>();
+
+ /**
+ * Set of methods that should be suppressed.
+ */
+ private static final Set<Field> suppressField = new HashSet<Field>();
+
+ /**
+ * Set of field types that should always be suppressed regardless of
+ * instance.
+ */
+ private static final Set<String> suppressFieldTypes = new HashSet<String>();
+
+ /**
+ * Set of runnables that will be executed after the test (method) is completed.
+ */
+ private static final Set<Runnable> afterMethodRunners = new HashSet<Runnable>();
+
+ /**
+ * Clear all state of the mock repository except for static initializers.
+ * The reason for not clearing static initializers is that when running in a
+ * suite with many tests the clear method is invoked after each test. This
+ * means that before the test that needs to suppress the static initializer
+ * has been reach the state of the MockRepository would have been wiped out.
+ * This is generally not a problem because most state will be added again
+ * but suppression of static initializers are different because this state
+ * can only be set once per class per CL. That's why we cannot remove this
+ * state.
+ */
+ public synchronized static void clear() {
+ newSubstitutions.clear();
+ classMocks.clear();
+ instanceMocks.clear();
+ objectsToAutomaticallyReplayAndVerify.clear();
+ additionalState.clear();
+ suppressConstructor.clear();
+ suppressMethod.clear();
+ substituteReturnValues.clear();
+ suppressField.clear();
+ suppressFieldTypes.clear();
+ methodProxies.clear();
+ for (Runnable runnable : afterMethodRunners) {
+ runnable.run();
+ }
+ afterMethodRunners.clear();
+ }
+
+ /**
+ * Removes an object from the MockRepository if it exists.
+ */
+ public static void remove(Object mock) {
+ if (mock instanceof Class<?>) {
+ if (newSubstitutions.containsKey(mock)) {
+ newSubstitutions.remove(mock);
+ }
+ if (classMocks.containsKey(mock)) {
+ classMocks.remove(mock);
+ }
+ } else if (instanceMocks.containsKey(mock)) {
+ instanceMocks.remove(mock);
+ }
+ }
+
+ public static synchronized MethodInvocationControl getStaticMethodInvocationControl(Class<?> type) {
+ return classMocks.get(type);
+ }
+
+ public static synchronized MethodInvocationControl putStaticMethodInvocationControl(Class<?> type, MethodInvocationControl invocationControl) {
+ return classMocks.put(type, invocationControl);
+ }
+
+ public static synchronized MethodInvocationControl removeClassMethodInvocationControl(Class<?> type) {
+ return classMocks.remove(type);
+ }
+
+ public static synchronized MethodInvocationControl getInstanceMethodInvocationControl(Object instance) {
+ return instanceMocks.get(instance);
+ }
+
+ public static synchronized MethodInvocationControl putInstanceMethodInvocationControl(Object instance, MethodInvocationControl invocationControl) {
+ return instanceMocks.put(instance, invocationControl);
+ }
+
+ public static synchronized MethodInvocationControl removeInstanceMethodInvocationControl(Class<?> type) {
+ return classMocks.remove(type);
+ }
+
+ public static synchronized NewInvocationControl<?> getNewInstanceControl(Class<?> type) {
+ return newSubstitutions.get(type);
+ }
+
+ public static synchronized NewInvocationControl<?> putNewInstanceControl(Class<?> type, NewInvocationControl<?> control) {
+ return newSubstitutions.put(type, control);
+ }
+
+ /**
+ * Add a fully qualified class name for a class that should have its static
+ * initializers suppressed.
+ *
+ * @param className
+ * The fully qualified class name for a class that should have
+ * its static initializers suppressed.
+ */
+ public static synchronized void addSuppressStaticInitializer(String className) {
+ suppressStaticInitializers.add(className);
+ }
+
+ /**
+ * Remove a fully qualified class name for a class that should no longer
+ * have its static initializers suppressed.
+ *
+ * @param className
+ * The fully qualified class name for a class that should no
+ * longer have its static initializers suppressed.
+ */
+ public static synchronized void removeSuppressStaticInitializer(String className) {
+ suppressStaticInitializers.remove(className);
+ }
+
+ /**
+ * Check whether or not a class with the fully qualified name should have
+ * its static initializers suppressed.
+ *
+ * @param className
+ * <code>true</code> if class with the fully qualified name
+ * <code>className</code> should have its static initializers
+ * suppressed, <code>false</code> otherwise.
+ */
+ public static synchronized boolean shouldSuppressStaticInitializerFor(String className) {
+ return suppressStaticInitializers.contains(className);
+ }
+
+ /**
+ * @return All classes that should be automatically replayed or verified.
+ */
+ public static synchronized Set<Object> getObjectsToAutomaticallyReplayAndVerify() {
+ return Collections.unmodifiableSet(objectsToAutomaticallyReplayAndVerify);
+ }
+
+ /**
+ * Add classes that should be automatically replayed or verified.
+ */
+ public static synchronized void addObjectsToAutomaticallyReplayAndVerify(Object... objects) {
+ for (Object mock : objects) {
+ objectsToAutomaticallyReplayAndVerify.add(mock);
+ }
+ }
+
+ /**
+ * When a mock framework API needs to store additional state not applicable
+ * for the other methods, it may use this method to do so.
+ *
+ * @param key
+ * The key under which the <tt>value</tt> is stored.
+ * @param value
+ * The value to store under the specified <tt>key</tt>.
+ * @return The previous object under the specified <tt>key</tt> or
+ * <code>null</code>.
+ */
+ public static synchronized Object putAdditionalState(String key, Object value) {
+ return additionalState.put(key, value);
+ }
+
+ public static synchronized Object removeAdditionalState(String key) {
+ return additionalState.remove(key);
+ }
+
+ public static synchronized InvocationHandler removeMethodProxy(Method method) {
+ return methodProxies.remove(method);
+ }
+
+ /**
+ * Retrieve state based on the supplied key.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T getAdditionalState(String key) {
+ return (T) additionalState.get(key);
+ }
+
+ /**
+ * Add a method to suppress.
+ *
+ * @param method
+ * The method to suppress.
+ */
+ public static synchronized void addMethodToSuppress(Method method) {
+ suppressMethod.add(method);
+ }
+
+ /**
+ * Add a field to suppress.
+ *
+ * @param field
+ * The field to suppress.
+ */
+ public static synchronized void addFieldToSuppress(Field field) {
+ suppressField.add(field);
+ }
+
+ /**
+ * Add a field type to suppress. All fields of this type will be suppressed.
+ *
+ * @param fieldType
+ * The fully-qualified name to a type. All fields of this type
+ * will be suppressed.
+ */
+ public static synchronized void addFieldTypeToSuppress(String fieldType) {
+ suppressFieldTypes.add(fieldType);
+ }
+
+ /**
+ * Add a constructor to suppress.
+ *
+ * @param constructor
+ * The constructor to suppress.
+ */
+ public static synchronized void addConstructorToSuppress(Constructor<?> constructor) {
+ suppressConstructor.add(constructor);
+ }
+
+ /**
+ * @return <code>true</code> if the <tt>method</tt> should be proxied.
+ */
+ public static synchronized boolean hasMethodProxy(Method method) {
+ return methodProxies.containsKey(method);
+ }
+
+ /**
+ * @return <code>true</code> if the <tt>method</tt> should be suppressed.
+ */
+ public static synchronized boolean shouldSuppressMethod(Method method,
+ Class<?> objectType) throws ClassNotFoundException {
+ for (Method suppressedMethod : suppressMethod) {
+ Class<?> suppressedMethodClass = suppressedMethod
+ .getDeclaringClass();
+ if (suppressedMethodClass.getClass().isAssignableFrom(
+ objectType.getClass())
+ && suppressedMethod.getName().equals(method.getName())
+ && ClassLocator.getCallerClass().getName()
+ .equals(suppressedMethodClass.getName())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @return <code>true</code> if the <tt>field</tt> should be suppressed.
+ */
+ public static synchronized boolean shouldSuppressField(Field field) {
+ return suppressField.contains(field) || suppressFieldTypes.contains(field.getType().getName());
+ }
+
+ /**
+ * @return <code>true</code> if the <tt>constructor</tt> should be
+ * suppressed.
+ */
+ public static synchronized boolean shouldSuppressConstructor(Constructor<?> constructor) {
+ return suppressConstructor.contains(constructor);
+ }
+
+ /**
+ * @return <code>true</code> if the <tt>method</tt> has a substitute return
+ * value.
+ */
+ public static synchronized boolean shouldStubMethod(Method method) {
+ return substituteReturnValues.containsKey(method);
+ }
+
+ /**
+ * @return The substitute return value for a particular method, may be
+ * <code>null</code>.
+ */
+ public static synchronized Object getMethodToStub(Method method) {
+ return substituteReturnValues.get(method);
+ }
+
+ /**
+ * Set a substitute return value for a method. Whenever this method will be
+ * called the <code>value</code> will be returned instead.
+ *
+ * @return The previous substitute value if any.
+ */
+ public static synchronized Object putMethodToStub(Method method, Object value) {
+ return substituteReturnValues.put(method, value);
+ }
+
+ /**
+ * @return The proxy for a particular method, may be <code>null</code>.
+ */
+ public static synchronized InvocationHandler getMethodProxy(Method method) {
+ return methodProxies.get(method);
+ }
+
+ /**
+ * Set a proxy for a method. Whenever this method is called the invocation
+ * handler will be invoked instead.
+ *
+ * @return The method proxy if any.
+ */
+ public static synchronized InvocationHandler putMethodProxy(Method method, InvocationHandler invocationHandler) {
+ return methodProxies.put(method, invocationHandler);
+ }
+
+ /**
+ * Add a {@link Runnable} that will be executed after each test
+ * @param runnable
+ */
+ public static synchronized void addAfterMethodRunner(Runnable runnable) {
+ afterMethodRunners.add(runnable);
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/PowerMockUtils.java b/core/src/main/java/org/powermock/core/PowerMockUtils.java
new file mode 100644
index 0000000..c20cbf4
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/PowerMockUtils.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import java.lang.reflect.Field;
+import java.util.Iterator;
+import java.util.Vector;
+
+public class PowerMockUtils {
+
+ /**
+ * Get an iterator of all classes loaded by the specific classloader.
+ *
+ * @param classLoader
+ * @return
+ * @throws NoSuchFieldException
+ * @throws IllegalAccessException
+ */
+ @SuppressWarnings("unchecked")
+ public static Iterator<Class<?>> getClassIterator(ClassLoader classLoader) throws NoSuchFieldException, IllegalAccessException {
+ Class<?> classLoaderClass = classLoader.getClass();
+ while (classLoaderClass != ClassLoader.class) {
+ classLoaderClass = classLoaderClass.getSuperclass();
+ }
+ Field classesField = classLoaderClass.getDeclaredField("classes");
+ classesField.setAccessible(true);
+ Vector<Class<?>> classes = (Vector<Class<?>>) classesField.get(classLoader);
+ return classes.iterator();
+ }
+
+ /**
+ *
+ * @param classLoader
+ * @throws NoSuchFieldException
+ * @throws IllegalAccessException
+ */
+ public static void printClassesLoadedByClassloader(ClassLoader classLoader, boolean includeParent) throws NoSuchFieldException,
+ IllegalAccessException {
+ while (classLoader != null) {
+ System.out.println("ClassLoader: " + classLoader);
+ for (Iterator<?> iter = PowerMockUtils.getClassIterator(classLoader); iter.hasNext();) {
+ System.out.println("\t" + iter.next());
+ }
+ if (includeParent) {
+ classLoader = classLoader.getParent();
+ } else {
+ classLoader = null;
+ }
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/WildcardMatcher.java b/core/src/main/java/org/powermock/core/WildcardMatcher.java
new file mode 100644
index 0000000..921f1cd
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/WildcardMatcher.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core;
+
+import java.util.Collection;
+
+/**
+ * Wildcard matcher.
+ */
+public class WildcardMatcher {
+
+ private static final char WILDCARD = '*';
+
+ /**
+ * Performs a wildcard matching for the text and pattern provided.
+ *
+ * @param text
+ * the text to be tested for matches.
+ *
+ * @param pattern
+ * the pattern to be matched for. This can contain the wildcard
+ * character '*' (asterisk).
+ *
+ * @return <tt>true</tt> if a match is found, <tt>false</tt> otherwise.
+ */
+ public static boolean matches(String text, String pattern) {
+ if (text == null) {
+ throw new IllegalArgumentException("text cannot be null");
+ }
+
+ text += '\0';
+ pattern += '\0';
+
+ int N = pattern.length();
+
+ boolean[] states = new boolean[N + 1];
+ boolean[] old = new boolean[N + 1];
+ old[0] = true;
+
+ for (int i = 0; i < text.length(); i++) {
+ char c = text.charAt(i);
+ states = new boolean[N + 1]; // initialized to false
+ for (int j = 0; j < N; j++) {
+ char p = pattern.charAt(j);
+
+ // hack to handle *'s that match 0 characters
+ if (old[j] && (p == WILDCARD))
+ old[j + 1] = true;
+
+ if (old[j] && (p == c))
+ states[j + 1] = true;
+ if (old[j] && (p == WILDCARD))
+ states[j] = true;
+ if (old[j] && (p == WILDCARD))
+ states[j + 1] = true;
+ }
+ old = states;
+ }
+ return states[N];
+
+ }
+
+ public static boolean matchesAny(Collection<String> patterns, String text) {
+ for (String pattern : patterns) {
+ if (matches(text, pattern)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean matchesAny(Iterable<String> patterns, String text) {
+ for (String string : patterns) {
+ if (matches(text, string)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static boolean matchesAny(String[] patterns, String text) {
+ for (String string : patterns) {
+ if (matches(text, string)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/agent/JavaAgentClassRegister.java b/core/src/main/java/org/powermock/core/agent/JavaAgentClassRegister.java
new file mode 100644
index 0000000..193e63d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/agent/JavaAgentClassRegister.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.agent;
+
+/**
+ * This register contains information about which class has been modified by PowerMock Java Agent.
+ */
+public interface JavaAgentClassRegister {
+
+ /**
+ * Check if class with <code>className</code> has been modified for the given class loader
+ * @param classLoader - {@link ClassLoader} for that class should be checked
+ * @param className - name of class
+ * @return <code>true</code> if the given class has been modified, otherwise <code>false</code>
+ */
+ boolean isModifiedByAgent(ClassLoader classLoader, String className);
+
+ /**
+ * Register that the class with name <code>className</code> has been modified for the given class loader.
+ * @param loader - {@link ClassLoader} for that class has been modified.
+ * @param className - name of the class which has been modified.
+ */
+ void registerClass(ClassLoader loader, String className);
+
+ /**
+ * Remove all registered classes for all class loaders.
+ */
+ void clear();
+}
diff --git a/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegister.java b/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegister.java
new file mode 100644
index 0000000..d5bffc8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegister.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.agent;
+
+/**
+ * Instance of class should set/clear an instance of the JavaAgentClassRegister
+ * in Mockito Frameworks classes
+ */
+public interface JavaAgentFrameworkRegister {
+
+ /**
+ * Set the <code>javaAgentClassRegister</code> to current loaded mocking framework.
+ * @param javaAgentClassRegister - an instance of {@link JavaAgentClassRegister} which should be set to
+ * frameworks classes.
+ */
+ void set(JavaAgentClassRegister javaAgentClassRegister);
+
+ /**
+ * Remove all links to JavaAgentClassRegister
+ */
+ void clear();
+
+}
diff --git a/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegisterFactory.java b/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegisterFactory.java
new file mode 100644
index 0000000..d3f6444
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/agent/JavaAgentFrameworkRegisterFactory.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.agent;
+
+import org.powermock.reflect.Whitebox;
+
+/**
+ * Factory to create an instance of JavaAgentFrameworkRegister,
+ * depends on which mocking framework is loaded in runtime.
+ */
+public class JavaAgentFrameworkRegisterFactory {
+
+ public static JavaAgentFrameworkRegister create() {
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ return getInstanceForClassLoader(classLoader);
+ }
+
+ private static JavaAgentFrameworkRegister getInstanceForClassLoader(ClassLoader classLoader) {
+ Class<JavaAgentFrameworkRegister> frameworkReporterClass = getJavaAgentFrameworkRegisterClass(classLoader);
+ return Whitebox.newInstance(frameworkReporterClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Class<JavaAgentFrameworkRegister> getJavaAgentFrameworkRegisterClass(ClassLoader classLoader) {
+ Class<JavaAgentFrameworkRegister> agentFrameworkRegisterClass;
+ try {
+ agentFrameworkRegisterClass = (Class<JavaAgentFrameworkRegister>) classLoader.loadClass(getImplementerClassName());
+ } catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ return agentFrameworkRegisterClass;
+ }
+
+ @SuppressWarnings("SameReturnValue")
+ private static String getImplementerClassName() {
+ return "org.powermock.api.extension.agent.JavaAgentFrameworkRegisterImpl";
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/ClassPathAdjuster.java b/core/src/main/java/org/powermock/core/classloader/ClassPathAdjuster.java
new file mode 100644
index 0000000..c81328f
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/ClassPathAdjuster.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2013 Jonas Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.classloader;
+
+import javassist.ClassPool;
+
+import org.powermock.core.classloader.annotations.UseClassPathAdjuster;
+
+/**
+ * This interface can be used to adjust the classpath used by powermock to locate
+ * class files. Use the @{@link UseClassPathAdjuster} to activate.
+ */
+public interface ClassPathAdjuster {
+ void adjustClassPath(ClassPool classPool);
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/DeferSupportingClassLoader.java b/core/src/main/java/org/powermock/core/classloader/DeferSupportingClassLoader.java
new file mode 100644
index 0000000..b189268
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/DeferSupportingClassLoader.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader;
+
+import javassist.Loader;
+import org.powermock.core.WildcardMatcher;
+import org.powermock.reflect.Whitebox;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.SoftReference;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Defers classloading of system classes to a delegate.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+public abstract class DeferSupportingClassLoader extends Loader {
+ private final ConcurrentMap<String, SoftReference<Class<?>>> classes;
+
+ String[] deferPackages;
+
+ ClassLoader deferTo;
+
+ public void addIgnorePackage(String... packagesToIgnore) {
+ if (packagesToIgnore != null && packagesToIgnore.length > 0) {
+ final int previousLength = deferPackages.length;
+ String[] newDeferPackages = new String[previousLength + packagesToIgnore.length];
+ System.arraycopy(deferPackages, 0, newDeferPackages, 0, previousLength);
+ System.arraycopy(packagesToIgnore, 0, newDeferPackages, previousLength, packagesToIgnore.length);
+ deferPackages = newDeferPackages;
+ }
+ }
+
+ DeferSupportingClassLoader(ClassLoader classloader, String deferPackages[]) {
+ if (classloader == null) {
+ deferTo = ClassLoader.getSystemClassLoader();
+ } else {
+ deferTo = classloader;
+ }
+ classes = new ConcurrentHashMap<String, SoftReference<Class<?>>>();
+ this.deferPackages = deferPackages;
+ }
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ SoftReference<Class<?>> reference = classes.get(name);
+ if (reference == null || reference.get() == null) {
+ final Class<?> clazz;
+ if (shouldDefer(deferPackages, name)) {
+ clazz = deferTo.loadClass(name);
+ } else {
+ clazz = loadModifiedClass(name);
+ }
+ if (resolve) {
+ resolveClass(clazz);
+ }
+ classes.put(name, (reference = new SoftReference<Class<?>>(clazz)));
+ }
+ return reference.get();
+ }
+
+ boolean shouldDefer(String[] packages, String name) {
+ for (String packageToCheck : packages) {
+ if (deferConditionMatches(name, packageToCheck)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean deferConditionMatches(String name, String packageName) {
+ final boolean wildcardMatch = WildcardMatcher.matches(name, packageName);
+ return wildcardMatch && !(shouldLoadUnmodifiedClass(name) || shouldModifyClass(name));
+ }
+
+ private boolean shouldIgnore(Iterable<String> packages, String name) {
+ for (String ignore : packages) {
+ if (WildcardMatcher.matches(ignore, name)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ boolean shouldIgnore(String[] packages, String name) {
+ for (String ignore : packages) {
+ if (WildcardMatcher.matches(name, ignore)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Finds the resource with the specified name on the search path.
+ *
+ * @param name the name of the resource
+ * @return a <code>URL</code> for the resource, or <code>null</code> if the
+ * resource could not be found.
+ */
+ @Override
+ protected URL findResource(String name) {
+ try {
+ return Whitebox.invokeMethod(deferTo, "findResource", name);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ protected Enumeration<URL> findResources(String name) throws IOException {
+ try {
+ return Whitebox.invokeMethod(deferTo, "findResources", name);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public URL getResource(String s) {
+ return deferTo.getResource(s);
+ }
+
+ @Override
+ public InputStream getResourceAsStream(String s) {
+ return deferTo.getResourceAsStream(s);
+ }
+
+ @Override
+ public Enumeration<URL> getResources(String name) throws IOException {
+ // If deferTo is already the parent, then we'd end up returning two copies of each resource...
+ if (deferTo.equals(getParent()))
+ return deferTo.getResources(name);
+ else
+ return super.getResources(name);
+ }
+
+ protected boolean shouldModify(Iterable<String> packages, String name) {
+ return !shouldIgnore(packages, name);
+ }
+
+ protected abstract Class<?> loadModifiedClass(String s) throws ClassFormatError, ClassNotFoundException;
+
+ protected abstract boolean shouldModifyClass(String s);
+
+ protected abstract boolean shouldLoadUnmodifiedClass(String className);
+
+ /**
+ * Register a class to the cache of this classloader
+ */
+ public void cache(Class<?> cls) {
+ if (cls != null) {
+ classes.put(cls.getName(), new SoftReference<Class<?>>(cls));
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarker.java b/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarker.java
new file mode 100644
index 0000000..520d9b8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarker.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.classloader;
+
+import javassist.CtClass;
+
+/**
+ * Instance of this interface can be used to mark {@link CtClass} that it was created and loaded by PowerMock
+ */
+public interface JavaAssistClassMarker {
+ /**
+ * Mark type as loaded by PowerMock
+ * @param type to mark.
+ */
+ void mark(CtClass type);
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarkerFactory.java b/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarkerFactory.java
new file mode 100644
index 0000000..aef14db
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/JavaAssistClassMarkerFactory.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.classloader;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+
+/**
+ *
+ */
+public class JavaAssistClassMarkerFactory {
+
+ public static JavaAssistClassMarker createClassMarker(ClassPool classPool) {
+ return new InterfaceJavaAssistClassMarker(classPool);
+ }
+
+ /**
+ * The implementation of the {@link JavaAssistClassMarker} which use an interface to mark type.
+ * @see PowerMockModified
+ */
+ private static class InterfaceJavaAssistClassMarker implements JavaAssistClassMarker {
+
+ private final ClassPool classPool;
+
+ InterfaceJavaAssistClassMarker(ClassPool classPool) {
+ this.classPool = classPool;
+ }
+
+ @Override
+ public void mark(CtClass type) {
+ CtClass powerMockInterface = classPool.makeInterface("org.powermock.core.classloader.PowerMockModified");
+
+ type.addInterface(powerMockInterface);
+
+ powerMockInterface.detach();
+
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/MockClassLoader.java b/core/src/main/java/org/powermock/core/classloader/MockClassLoader.java
new file mode 100644
index 0000000..a303e8e
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/MockClassLoader.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.core.classloader;
+
+import javassist.ClassClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import org.powermock.core.ClassReplicaCreator;
+import org.powermock.core.WildcardMatcher;
+import org.powermock.core.classloader.annotations.UseClassPathAdjuster;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.core.spi.support.InvocationSubstitute;
+import org.powermock.core.transformers.MockTransformer;
+
+import java.security.ProtectionDomain;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Mock all classes except system classes.
+ * <p/>
+ * Notice that there are two different types of classes that are not mocked:
+ * <ol>
+ * <li>system classes are deferred to another classloader</li>
+ * <li>testing framework classes are loaded, but not modified</li>
+ * </ol>
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+public class MockClassLoader extends DeferSupportingClassLoader {
+
+ /**
+ * Pass this string to the constructor to indicate that all classes should
+ * be modified.
+ */
+ public static final String MODIFY_ALL_CLASSES = "*";
+
+ private static final String CGLIB_ENHANCER = "net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$";
+ private static final String CGLIB_METHOD_WRAPPER = "net.sf.cglib.core.MethodWrapper$MethodWrapperKey$$KeyFactoryByCGLIB";
+ private final JavaAssistClassMarker javaAssistClassMarker;
+
+ private List<MockTransformer> mockTransformerChain;
+
+ private final Set<String> modify = Collections.synchronizedSet(new HashSet<String>());
+
+ /*
+ * Classes not deferred but loaded by the mock class loader but they're not
+ * modified.
+ */
+ private final String[] packagesToLoadButNotModify = new String[]{"org.junit.", "junit.", "org.testng.",
+ "org.easymock.",
+ "net.sf.cglib.", "javassist.",
+ "org.powermock.modules.junit4.internal.", "org.powermock.modules.junit4.legacy.internal.",
+ "org.powermock.modules.junit3.internal.",
+ "org.powermock"};
+
+ private final String[] specificClassesToLoadButNotModify = new String[]{InvocationSubstitute.class.getName(),
+ PowerMockPolicy.class.getName(),
+ ClassReplicaCreator.class.getName()};
+
+ /*
+ * Classes that should always be deferred regardless of what the user
+ * specifies in annotations etc.
+ */
+ private static final String[] packagesToBeDeferred = new String[]{"org.hamcrest.*", "java.*",
+ "javax.accessibility.*", "sun.*", "org.junit.*", "org.testng.*",
+ "junit.*", "org.pitest.*", "org.powermock.modules.junit4.common.internal.*",
+ "org.powermock.modules.junit3.internal.PowerMockJUnit3RunnerDelegate*",
+ "org.powermock.core*", "org.jacoco.agent.rt.*"};
+
+ private final ClassPool classPool = new ClassPool();
+
+ /**
+ * Creates a new instance of the {@link MockClassLoader} based on the
+ * following parameters:
+ *
+ * @param classesToMock The classes that must be modified to prepare for testability.
+ * @param packagesToDefer Classes in these packages will be defered to the system
+ * class-loader.
+ */
+ public MockClassLoader(String[] classesToMock, String[] packagesToDefer, UseClassPathAdjuster useClassPathAdjuster) {
+ super(MockClassLoader.class.getClassLoader(), getPackagesToDefer(packagesToDefer));
+
+ addClassesToModify(classesToMock);
+ classPool.appendClassPath(new ClassClassPath(this.getClass()));
+ if (useClassPathAdjuster != null) {
+ try {
+ Class<? extends ClassPathAdjuster> value = useClassPathAdjuster.value();
+ ClassPathAdjuster classPathAdjuster = value.newInstance();
+ classPathAdjuster.adjustClassPath(classPool);
+ } catch (Exception e) {
+ throw new RuntimeException("Error instantiating class path adjuster", e);
+ }
+ }
+ javaAssistClassMarker = JavaAssistClassMarkerFactory.createClassMarker(classPool);
+ }
+
+ MockClassLoader() {
+ this(new String[0], new String[0]);
+ }
+
+ private static String[] getPackagesToDefer(final String[] additionalDeferPackages) {
+ final int additionalIgnorePackagesLength = additionalDeferPackages == null ? 0 : additionalDeferPackages.length;
+ final int defaultDeferPackagesLength = packagesToBeDeferred.length;
+ final int allIgnoreLength = defaultDeferPackagesLength + additionalIgnorePackagesLength;
+ final String[] allPackagesToBeIgnored = new String[allIgnoreLength];
+ if (allIgnoreLength > defaultDeferPackagesLength) {
+ System.arraycopy(packagesToBeDeferred, 0, allPackagesToBeIgnored, 0, defaultDeferPackagesLength);
+ System.arraycopy(additionalDeferPackages != null ? additionalDeferPackages : new String[0], 0, allPackagesToBeIgnored, defaultDeferPackagesLength,
+ additionalIgnorePackagesLength);
+ return allPackagesToBeIgnored;
+ }
+ return packagesToBeDeferred;
+ }
+
+ /**
+ * Creates a new instance of the {@link MockClassLoader} based on the
+ * following parameters:
+ *
+ * @param classesToMock The classes that must be modified to prepare for testability.
+ * @param packagesToDefer Classes in these packages will be defered to the system
+ * class-loader.
+ */
+ public MockClassLoader(String[] classesToMock, String[] packagesToDefer) {
+ this(classesToMock, packagesToDefer, null);
+ }
+
+ /**
+ * Creates a new instance of the {@link MockClassLoader} based on the
+ * following parameters:
+ *
+ * @param classesToMock The classes that must be modified to prepare for testability.
+ */
+ public MockClassLoader(String[] classesToMock, UseClassPathAdjuster useClassPathAdjuster) {
+ this(classesToMock, new String[0], useClassPathAdjuster);
+ }
+
+ /**
+ * Creates a new instance of the {@link MockClassLoader} based on the
+ * following parameters:
+ *
+ * @param classesToMock The classes that must be modified to prepare for testability.
+ */
+ public MockClassLoader(String[] classesToMock) {
+ this(classesToMock, new String[0], null);
+ }
+
+ /**
+ * Add classes that will be loaded by the mock classloader, i.e. these
+ * classes will be byte-code manipulated to allow for testing. Any classes
+ * contained in the {@link #packagesToBeDeferred} will be ignored. How ever
+ * classes added here have precedence over additionally deferred (ignored)
+ * packages (those ignored by the user using @PrepareForTest).
+ *
+ * @param classes The fully qualified name of the classes that will be appended
+ * to the list of classes that will be byte-code modified to
+ * enable testability.
+ */
+ public final void addClassesToModify(String... classes) {
+ if (classes != null) {
+ for (String clazz : classes) {
+ if (!shouldDefer(packagesToBeDeferred, clazz)) {
+ modify.add(clazz);
+ }
+ }
+ }
+ }
+
+ @Override
+ protected Class<?> loadModifiedClass(String s) throws ClassFormatError, ClassNotFoundException {
+ Class<?> loadedClass;
+
+ Class<?> deferClass = deferTo.loadClass(s);
+ if (shouldModify(s) && !shouldLoadWithMockClassloaderWithoutModifications(s)) {
+ loadedClass = loadMockClass(s);
+ } else {
+ loadedClass = loadUnmockedClass(s, deferClass.getProtectionDomain());
+ }
+ return loadedClass;
+ }
+
+ private boolean shouldModify(String className) {
+ final boolean shouldIgnoreClass = shouldIgnore(deferPackages, className);
+ final boolean shouldModifyAll = shouldModifyAll();
+ if (shouldModifyAll) {
+ return !shouldIgnoreClass;
+ } else {
+ /*
+ * Never mind if we should ignore the class here since
+ * classes added by prepared for test should (i.e. those added in "modify")
+ * have precedence over ignored packages.
+ */
+ return WildcardMatcher.matchesAny(modify, className);
+ }
+ }
+
+ private boolean shouldModifyAll() {
+ return (modify.size() == 1 && modify.iterator().next().equals(MODIFY_ALL_CLASSES));
+ }
+
+ private Class<?> loadUnmockedClass(String name, ProtectionDomain protectionDomain)
+ throws ClassFormatError, ClassNotFoundException {
+ byte bytes[] = null;
+ try {
+ /*
+ * TODO This if-statement is a VERY ugly hack to avoid the
+ * java.lang.ExceptionInInitializerError caused by
+ * "javassist.NotFoundException:
+ * net.sf.cglib.proxy.Enhancer$EnhancerKey$$KeyFactoryByCGLIB$$7fb24d72
+ * ". This happens after the
+ * se.jayway.examples.tests.privatefield.
+ * SimplePrivateFieldServiceClassTest#testUseService(..) tests has
+ * been run and all other tests will fail if this class is tried to
+ * be loaded. Atm I have found no solution other than this ugly hack
+ * to make it work. We really need to investigate the real cause of
+ * this behavior.
+ */
+ if (!name.startsWith(CGLIB_ENHANCER) && !name.startsWith(CGLIB_METHOD_WRAPPER)) {
+ final CtClass ctClass = classPool.get(name);
+ if (ctClass.isFrozen()) {
+ ctClass.defrost();
+ }
+ bytes = ctClass.toBytecode();
+ }
+ } catch (Exception e) {
+ if (e instanceof javassist.NotFoundException) {
+ throw new ClassNotFoundException();
+ } else {
+ throw new RuntimeException(e);
+ }
+
+ }
+ return bytes == null ? null : defineClass(name, bytes, 0, bytes.length, protectionDomain);
+ }
+
+ /**
+ * Load a mocked version of the class.
+ */
+ private Class<?> loadMockClass(String name) {
+
+ final byte[] clazz;
+
+ ClassPool.doPruning = false;
+ try {
+ CtClass type = classPool.get(name);
+ for (MockTransformer transformer : mockTransformerChain) {
+ type = transformer.transform(type);
+ }
+
+ javaAssistClassMarker.mark(type);
+
+ /*
+ * ClassPool may cause huge memory consumption if the number of CtClass
+ * objects becomes amazingly large (this rarely happens since Javassist
+ * tries to reduce memory consumption in various ways). To avoid this
+ * problem, you can explicitly remove an unnecessary CtClass object from
+ * the ClassPool. If you call detach() on a CtClass object, then that
+ * CtClass object is removed from the ClassPool.
+ */
+ type.detach();
+
+
+ clazz = type.toBytecode();
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to transform class with name " + name + ". Reason: "
+ + e.getMessage(), e);
+ }
+
+ return defineClass(name, clazz, 0, clazz.length);
+ }
+
+ public void setMockTransformerChain(List<MockTransformer> mockTransformerChain) {
+ this.mockTransformerChain = mockTransformerChain;
+ }
+
+ @Override
+ protected boolean shouldModifyClass(String s) {
+ return modify.contains(s);
+ }
+
+ @Override
+ protected boolean shouldLoadUnmodifiedClass(String className) {
+ for (String classNameToLoadButNotModify : specificClassesToLoadButNotModify) {
+ if (className.equals(classNameToLoadButNotModify)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean shouldLoadWithMockClassloaderWithoutModifications(String className) {
+ if (className.startsWith("org.powermock.example")) {
+ return false;
+ }
+ for (String packageToLoadButNotModify : packagesToLoadButNotModify) {
+ if (className.startsWith(packageToLoadButNotModify)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilder.java b/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilder.java
new file mode 100644
index 0000000..3ce3eec
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilder.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.classloader;
+
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.utils.ArrayUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MockClassLoader builder.
+ */
+public class MockClassLoaderBuilder {
+
+ private final List<MockTransformer> mockTransformerChain;
+ private String[] packagesToIgnore;
+ private String[] classesToModify;
+
+ MockClassLoaderBuilder() {
+ mockTransformerChain = new ArrayList<MockTransformer>(3);
+ }
+
+ public MockClassLoader build() {
+ MockClassLoader classLoader = new MockClassLoader();
+
+ classLoader.setMockTransformerChain(mockTransformerChain);
+ classLoader.addIgnorePackage(packagesToIgnore);
+ classLoader.addClassesToModify(classesToModify);
+
+ return classLoader;
+ }
+
+ public MockClassLoaderBuilder addMockTransformerChain(List<MockTransformer> mockTransformerChain) {
+ this.mockTransformerChain.addAll(mockTransformerChain);
+ return this;
+ }
+
+ public MockClassLoaderBuilder addIgnorePackage(String[] packagesToIgnore) {
+ this.packagesToIgnore = ArrayUtil.addAll(this.packagesToIgnore, packagesToIgnore);
+ return this;
+ }
+
+ public MockClassLoaderBuilder addClassesToModify(String[] classesToModify) {
+ this.classesToModify = ArrayUtil.addAll(this.classesToModify, classesToModify);
+ return this;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilders.java b/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilders.java
new file mode 100644
index 0000000..259fbb0
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/MockClassLoaderBuilders.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.classloader;
+
+/**
+ * Factory class for MockClassLoaderBuilder
+ */
+public class MockClassLoaderBuilders {
+
+ public static MockClassLoaderBuilder mockClassLoaderBuilder() {
+ return new MockClassLoaderBuilder();
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/PowerMockModified.java b/core/src/main/java/org/powermock/core/classloader/PowerMockModified.java
new file mode 100644
index 0000000..ebc4aaa
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/PowerMockModified.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.classloader;
+
+/**
+ * Interface marker. If an interface extends the PowerMockModified or a class implements
+ * PowerMockModified this means that the interface/class has been modified by PowerMock.
+ */
+public interface PowerMockModified {
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/Mock.java b/core/src/main/java/org/powermock/core/classloader/annotations/Mock.java
new file mode 100644
index 0000000..1686218
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/Mock.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.classloader.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation can be placed on those fields in your test class that should
+ * be mocked. This eliminates the need to setup and tear-down mocks manually
+ * which minimizes repetitive test code and makes the test more readable. In
+ * order for PowerMock to control the life-cycle of the mocks you must supply
+ * the {@link PowerMockListener} annotation to the class-level of the test case.
+ * For example:
+ *
+ * <pre>
+ * ...
+ * @PowerMockListener(AnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @Mock
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ * Note that you can also create partial mocks by using the annotation. Let's
+ * say that the PersonService has a method called "getPerson" and another method
+ * called "savePerson" and these are the only two methods that you'd like to
+ * mock. Rewriting the previous example to accommodate this will give us the
+ * following test:
+ *
+ * <pre>
+ * ...
+ * @PowerMockListener(EasyMockAnnotationEnabler.class)
+ * public class PersonServiceTest {
+ *
+ * @Mock({"getPerson", "savePerson"})
+ * private PersonDao personDaoMock;
+ *
+ * private PersonService classUnderTest;
+ *
+ * @Before
+ * public void setUp() {
+ * classUnderTest = new PersonService(personDaoMock);
+ * }
+ * ...
+ * }
+ * </pre>
+ * <p>
+ *
+ * @deprecated Use Mock annotation in respective extension API instead. This
+ * annotation will be removed in an upcoming release.
+ */
+
+ at Target( { ElementType.FIELD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface Mock {
+ String[] value() default "";
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/MockPolicy.java b/core/src/main/java/org/powermock/core/classloader/annotations/MockPolicy.java
new file mode 100644
index 0000000..bc35751
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/MockPolicy.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader.annotations;
+
+import org.powermock.core.spi.PowerMockPolicy;
+
+import java.lang.annotation.*;
+
+/**
+ * A Mock Policy can be used to make it easier to unit test some code with
+ * PowerMock in isolation from a certain framework. A mock policy implementation
+ * can for example suppress some methods, suppress static initializers or
+ * intercept method calls and change their return value (for example to return a
+ * mock object) for a certain framework or set of classes or interfaces.
+ * <p>
+ * A mock policy can for example be implemented to avoid writing repetitive
+ * setup code for your tests. Say that you're using a framework X that in order
+ * for you to test it requires that certain methods should always return a mock
+ * implementation. Perhaps some static initializers must be suppressed as well.
+ * Instead of copying this code between tests it would be a good idea to write a
+ * reusable mock policy.
+ */
+ at Target( { ElementType.TYPE })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface MockPolicy {
+ /**
+ * @return A list of mock policies that should be used in the test class.
+ */
+ Class<? extends PowerMockPolicy>[] value();
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockIgnore.java b/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockIgnore.java
new file mode 100644
index 0000000..5e6d1a0
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockIgnore.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation tells PowerMock to defer the loading of classes with the
+ * names supplied to {@link #value()} to the system classloader.
+ * <p>
+ * For example suppose you'd like to defer the loading of all classes in the
+ * <tt>org.myproject</tt> package and all its sub-packages but you still like to
+ * prepare "MyClass" for test. Then you do like this:
+ *
+ * <pre>
+ * @PowerMockIgnore("org.myproject.*")
+ * @PrepareForTest(MyClass.class)
+ * @RunWith(PowerMockRunner.class)
+ * public class MyTest {
+ * ...
+ * }
+ *
+ * </pre>
+ *
+ * This is useful in situations when you have e.g. a test/assertion utility
+ * framework (such as something similar to Hamcrest) whose classes must be
+ * loaded by the same classloader as EasyMock, JUnit and PowerMock etc.
+ * <p>
+ * Note that the {@link PrepareForTest} and {@link PrepareOnlyThisForTest} will
+ * have precedence over this annotation. This annotation will have precedence
+ * over the {@link PrepareEverythingForTest} annotation.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface PowerMockIgnore {
+ String[] value() default "";
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockListener.java b/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockListener.java
new file mode 100644
index 0000000..b99f632
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/PowerMockListener.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.classloader.annotations;
+
+import org.powermock.core.spi.PowerMockTestListener;
+
+import java.lang.annotation.*;
+
+/**
+ * The PowerMock listener annotation can be used to tell PowerMock which
+ * listeners should be instantiated and invoked during a test. A listener is
+ * invoked according to the events specified in the
+ * {@link PowerMockTestListener} interface.
+ */
+ at Target( { ElementType.TYPE })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface PowerMockListener {
+ Class<? extends PowerMockTestListener>[] value();
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/PrepareEverythingForTest.java b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareEverythingForTest.java
new file mode 100644
index 0000000..c110d96
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareEverythingForTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation tells PowerMock to prepare all classes (except certain system
+ * and test related classes) for test. Note that static initializers are
+ * <i>not</i> removed.
+ * <p>
+ * The annotation should always be combined with the
+ * <code>@RunWith(PowerMockRunner.class)</code> if using junit 4.x or
+ *
+ * <pre>
+ * public static TestSuite suite() throws Exception {
+ * return new PowerMockSuite(MyTestCase.class);
+ * }
+ * </pre>
+ *
+ * if using junit3.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface PrepareEverythingForTest {
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/PrepareForTest.java b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareForTest.java
new file mode 100644
index 0000000..c5abe45
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareForTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader.annotations;
+
+import org.powermock.core.IndicateReloadClass;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation tells PowerMock to prepare certain classes for testing.
+ * Classes needed to be defined using this annotation are typically those that
+ * needs to be byte-code manipulated. This includes final classes, classes with
+ * final, private, static or native methods that should be mocked and also
+ * classes that should be return a mock object upon instantiation.
+ * <p>
+ * This annotation can be placed at both test classes and individual test
+ * methods. If placed on a class all test methods in this test class will be
+ * handled by PowerMock (to allow for testability). To override this behavior
+ * for a single method just place a <code>@PrepareForTest</code> annotation
+ * on the specific test method. This is useful in situations where for example
+ * you'd like to modify class X in test method A but in test method B you want X
+ * to be left intact. In situations like this you place a
+ * <code>@PrepareForTest</code> on method B and exclude class X from the
+ * {@link #value()} list.
+ * <p>
+ * Sometimes you need to prepare inner classes for testing, this can be done by
+ * suppling the fully-qualified name of the inner-class that should be mocked to
+ * the {@link #fullyQualifiedNames()} list.
+ * <p>
+ * You can also prepare whole packages for test by using wildcards:
+ *
+ * <pre>
+ * @PrepareForTest(fullyQualifiedNames="com.mypackage.*")
+ * </pre>
+ *
+ * <p>
+ * The annotation should always be combined with the
+ * <code>@RunWith(PowerMockRunner.class)</code> if using junit 4.x or
+ *
+ * <pre>
+ * public static TestSuite suite() throws Exception {
+ * return new PowerMockSuite(MyTestCase.class);
+ * }
+ * </pre>
+ *
+ * if using junit3.
+ * <p>
+ * The difference between this annotation and the {@link PrepareOnlyThisForTest}
+ * annotation is that this annotation modifies the specified classes and all its
+ * super classes whereas the {@link PrepareOnlyThisForTest} annotation
+ * manipulates <i>only</i> the specified classes.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface PrepareForTest {
+ Class<?>[] value() default IndicateReloadClass.class;
+
+ String[] fullyQualifiedNames() default "";
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/PrepareOnlyThisForTest.java b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareOnlyThisForTest.java
new file mode 100644
index 0000000..8dc4dc8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/PrepareOnlyThisForTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader.annotations;
+
+import org.powermock.core.IndicateReloadClass;
+
+import java.lang.annotation.*;
+
+/**
+ * This annotation tells PowerMock to prepare certain classes for testing.
+ * Classes needed to be defined using this annotation are typically those that
+ * needs to be byte-code manipulated. This includes final classes, classes with
+ * final, private, static or native methods that should be mocked and also
+ * classes that should be return a mock object upon instantiation.
+ * <p>
+ * This annotation can be placed at both test classes and individual test
+ * methods. If placed on a class all test methods in this test class will be
+ * handled by PowerMock (to allow for testability). To override this behavior
+ * for a single method just place a <code>@PrepareForTest</code> annotation
+ * on the specific test method. This is useful in situations where for example
+ * you'd like to modify class X in test method A but in test method B you want X
+ * to be left intact. In situations like this you place a
+ * <code>@PrepareForTest</code> on method B and exclude class X from the
+ * {@link #value()} list.
+ * <p>
+ * Sometimes you need to prepare inner classes for testing, this can be done by
+ * suppling the fully-qualified name of the inner-class that should be mocked to
+ * the {@link #fullyQualifiedNames()} list.
+ *
+ * <p>
+ * The annotation should always be combined with the
+ * <code>@RunWith(PowerMockRunner.class)</code> if using junit 4.x or
+ *
+ * <pre>
+ * public static TestSuite suite() throws Exception {
+ * return new PowerMockSuite(MyTestCase.class);
+ * }
+ * </pre>
+ *
+ * if using junit3.
+ * <p>
+ * The difference between this annotation and the {@link PrepareForTest}
+ * annotation is that this annotation only modifies the specified classes
+ * whereas the {@link PrepareForTest} annotation manipulates the full class
+ * hierarchy. This annotation is recommend if you want full control over which
+ * classes that are byte-code manipulated.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface PrepareOnlyThisForTest {
+ Class<?>[] value() default IndicateReloadClass.class;
+
+ String[] fullyQualifiedNames() default "";
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/SuppressStaticInitializationFor.java b/core/src/main/java/org/powermock/core/classloader/annotations/SuppressStaticInitializationFor.java
new file mode 100644
index 0000000..e1e5708
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/SuppressStaticInitializationFor.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.classloader.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * Use this annotation to suppress static initializers (constructors) for one or
+ * more classes.
+ * <p>
+ * The reason why an annotation is needed for this is because we need to know at
+ * <strong>load-time</strong> if the static constructor execution for this
+ * class should be skipped or not. Unfortunately we cannot pass the class as the
+ * value parameter to the annotation (and thus get type-safe values) because
+ * then the class would be loaded before PowerMock could have suppressed its
+ * constructor.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface SuppressStaticInitializationFor {
+ String[] value() default "";
+}
diff --git a/core/src/main/java/org/powermock/core/classloader/annotations/UseClassPathAdjuster.java b/core/src/main/java/org/powermock/core/classloader/annotations/UseClassPathAdjuster.java
new file mode 100644
index 0000000..1b8e362
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/classloader/annotations/UseClassPathAdjuster.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2013 Jonas Berlin
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.classloader.annotations;
+
+import java.lang.annotation.*;
+
+import org.powermock.core.classloader.ClassPathAdjuster;
+
+/**
+ * Use this annotation to enable adjusting of the class path used by powermock
+ * to locate class files.
+ */
+ at Target( { ElementType.TYPE, ElementType.METHOD })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+ at Inherited
+public @interface UseClassPathAdjuster {
+ Class<? extends ClassPathAdjuster> value();
+}
diff --git a/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporter.java b/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporter.java
new file mode 100644
index 0000000..47434a8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporter.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.reporter;
+
+/**
+ * The instance of the interface is used to replace default mocking frameworks
+ * exception message via message specific for PowerMock use-cases.
+ */
+public interface MockingFrameworkReporter {
+
+ /**
+ * Start replacing mocking frameworks exception message
+ */
+ void enable();
+
+ /**
+ * Stop replacing mocking frameworks exception message
+ */
+ void disable();
+
+}
diff --git a/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporterFactory.java b/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporterFactory.java
new file mode 100644
index 0000000..6ab5b12
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/reporter/MockingFrameworkReporterFactory.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.reporter;
+
+public interface MockingFrameworkReporterFactory {
+
+ MockingFrameworkReporter create();
+
+}
diff --git a/core/src/main/java/org/powermock/core/reporter/PowerMockReporter.java b/core/src/main/java/org/powermock/core/reporter/PowerMockReporter.java
new file mode 100644
index 0000000..e2cf9a4
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/reporter/PowerMockReporter.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.reporter;
+
+/**
+ * The interface is used to provide a user well-defined exception description.
+ */
+public interface PowerMockReporter {
+
+ <T> void classNotPrepared(Class<T> type);
+}
diff --git a/core/src/main/java/org/powermock/core/reporter/PowerMockReporterFactory.java b/core/src/main/java/org/powermock/core/reporter/PowerMockReporterFactory.java
new file mode 100644
index 0000000..e2823e3
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/reporter/PowerMockReporterFactory.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.reporter;
+
+/**
+ *
+ */
+ at SuppressWarnings("unused")
+public interface PowerMockReporterFactory {
+
+ PowerMockReporter createPowerMockReporter();
+
+}
diff --git a/core/src/main/java/org/powermock/core/spi/DefaultBehavior.java b/core/src/main/java/org/powermock/core/spi/DefaultBehavior.java
new file mode 100644
index 0000000..cb1f741
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/DefaultBehavior.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.spi;
+
+/**
+ * Interface that provides the replay, verify and reset behavior for mock
+ * objects and classes.
+ */
+public interface DefaultBehavior {
+
+ /**
+ * Replay the given objects or classes. May throw exception if replay is not
+ * needed or not supported.
+ *
+ * @param mock
+ * The object(s) to replay. May be <code>null</code>.
+ *
+ * @return the result of the replay (may be <code>null</code>).
+ */
+ Object replay(Object... mocks);
+
+ /**
+ * Verify the given objects or classes. May throw exception if verify is not
+ * needed or not supported.
+ *
+ * @param mock
+ * The object(s) to verify. May be <code>null</code>.
+ *
+ * @return the result of the verification (may be <code>null</code>).
+ */
+ Object verify(Object... mocks);
+
+ /**
+ * Reset the given objects or classes. May throw exception if reset is not
+ * needed or not supported.
+ *
+ * @param mock
+ * The object(s) to replay. May be <code>null</code>.
+ *
+ * @return the result of the replay (may be <code>null</code>).
+ */
+ Object reset(Object... mocks);
+
+}
diff --git a/core/src/main/java/org/powermock/core/spi/MethodInvocationControl.java b/core/src/main/java/org/powermock/core/spi/MethodInvocationControl.java
new file mode 100644
index 0000000..2863e10
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/MethodInvocationControl.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+
+/**
+ * The purpose of a method invocation control is to invoke a proxy to simulate a
+ * method call. It also has functionality to replay and verify mocks (which may
+ * not be needed for certain invocation controls) and to check whether a certain
+ * method is mocked or not.
+ *
+ */
+public interface MethodInvocationControl extends InvocationHandler, DefaultBehavior {
+
+ /**
+ * Determine whether a certain method is mocked by this Invocation Control.
+ *
+ * @param method
+ * The method that should be checked.
+ * @return <code>true</code> if the method is mocked, <code>false</code>
+ * otherwise.
+ */
+ public boolean isMocked(Method method);
+
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/powermock/core/spi/NewInvocationControl.java b/core/src/main/java/org/powermock/core/spi/NewInvocationControl.java
new file mode 100644
index 0000000..e6cf34d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/NewInvocationControl.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.spi;
+
+import org.powermock.core.spi.support.InvocationSubstitute;
+
+/**
+ * A new invocation control pairs up a {@link InvocationSubstitute} with the
+ * mock object created when invoking
+ * {@link InvocationSubstitute#performSubstitutionLogic(Object...)} object.
+ *
+ */
+public interface NewInvocationControl<T> extends DefaultBehavior {
+
+ /**
+ * Invoke the invocation control
+ */
+ Object invoke(Class<?> type, Object[] args, Class<?>[] sig) throws Exception;
+
+ /**
+ * Expect a call to the new instance substitution logic.
+ */
+ T expectSubstitutionLogic(Object... arguments) throws Exception;
+}
diff --git a/core/src/main/java/org/powermock/core/spi/PowerMockPolicy.java b/core/src/main/java/org/powermock/core/spi/PowerMockPolicy.java
new file mode 100644
index 0000000..b2ba8c4
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/PowerMockPolicy.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi;
+
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+
+/**
+ * This interface can be implemented to create policies for certain frameworks
+ * to make it easier for users to test their code in isolation from these
+ * frameworks. A mock policy implementation can for example suppress some
+ * methods, suppress static initializers or intercept method calls and change
+ * their return value (for example to return a mock object). <i>A mock policy
+ * implementation must be stateless</i>. The reason why there are two methods
+ * for applying settings is that PowerMock needs to know which classes that
+ * should be modified by the mock class loader <i>before</i> these classes have
+ * loaded. The {@link #applyClassLoadingPolicy(MockPolicyClassLoadingSettings)}
+ * tells PowerMock which classes that should be loaded and then the
+ * {@link #applyInterceptionPolicy(MockPolicyInterceptionSettings)} is called
+ * from the mock class-loader itself. This means you can create mocks for e.g.
+ * final and static methods in the
+ * {@link #applyInterceptionPolicy(MockPolicyInterceptionSettings)} which would
+ * not have been possible otherwise.
+ * <p>
+ * Since mock policies can be chained subsequent policies can override behavior
+ * of a previous policy. To avoid accidental overrides it's recommended
+ * <i>add</i> behavior instead of <i>setting</i> behavior since the latter
+ * overrides all previous configurations.
+ */
+public interface PowerMockPolicy {
+
+ /**
+ * Apply all class-loading related policies that must be present before the
+ * interception policies can take place.
+ *
+ * @param settings
+ * The settings objects where the class-loading policies can be
+ * applied.
+ */
+ void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings);
+
+ /**
+ * Apply the interception policies, for example which methods that should be
+ * suppressed or which methods that should be intercepted and return some
+ * else than their original value.
+ *
+ * @param settings
+ * The settings objects where the interception policies can be
+ * applied.
+ */
+ void applyInterceptionPolicy(MockPolicyInterceptionSettings settings);
+}
diff --git a/core/src/main/java/org/powermock/core/spi/PowerMockTestListener.java b/core/src/main/java/org/powermock/core/spi/PowerMockTestListener.java
new file mode 100644
index 0000000..c810e23
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/PowerMockTestListener.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi;
+
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+
+import java.lang.reflect.Method;
+
+/**
+ * This interface should be implemented by all PowerMock test listeners. The
+ * listener will be notified on the events present in this interface. Please
+ * note that a listener cannot hold state.
+ */
+public interface PowerMockTestListener {
+
+ /**
+ * Invoked once before the test run has started.
+ *
+ * @param testClass
+ * The type of the test to be executed.
+ * @param testMethods
+ * The test methods that will be executed during the test.
+ * @throws Exception
+ * If something unexpected occurs.
+ */
+ void beforeTestSuiteStarted(Class<?> testClass, Method[] testMethods) throws Exception;
+
+ /**
+ * Invoked before each test method.
+ *
+ * @param testInstance
+ * The test case instance.
+ * @param method
+ * The test method that is currently executed.
+ * @param arguments
+ * The arguments passed to the test method if any. May be an
+ * empty array but never <code>null</code>.
+ * @throws Exception
+ * If something unexpected occurs.
+ */
+ void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception;
+
+ /**
+ * Invoked after each test method.
+ *
+ * * @param testInstance The test case instance.
+ *
+ * @param method
+ * The test method that is currently executed.
+ * @param arguments
+ * The arguments passed to the test method if any. May be an
+ * empty array but never <code>null</code>.
+ * @param testResult
+ * The outcome of the test method.
+ * @throws Exception
+ * If something unexpected occurs.
+ */
+ void afterTestMethod(Object testInstance, Method method, Object[] arguments, TestMethodResult testResult) throws Exception;
+
+ /**
+ * Invoked after a test suite has ended.
+ *
+ * @param testClass
+ * The type of the test to be executed.
+ * @param methods
+ * The test methods that were executed during the test.
+ * @param testResult
+ * The outcome of the test suite.
+ * @throws Exception
+ * If something unexpected occurs.
+ */
+ void afterTestSuiteEnded(Class<?> testClass, Method[] methods, TestSuiteResult testResult) throws Exception;
+}
diff --git a/core/src/main/java/org/powermock/core/spi/listener/AnnotationEnablerListener.java b/core/src/main/java/org/powermock/core/spi/listener/AnnotationEnablerListener.java
new file mode 100644
index 0000000..b29e905
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/listener/AnnotationEnablerListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.listener;
+
+import org.powermock.core.spi.PowerMockTestListener;
+
+import java.lang.annotation.Annotation;
+
+public interface AnnotationEnablerListener extends PowerMockTestListener {
+
+ /**
+ * @return The mock annotations considered by this annotation enabler.
+ */
+ Class<? extends Annotation>[] getMockAnnotations();
+}
diff --git a/core/src/main/java/org/powermock/core/spi/support/AbstractPowerMockTestListenerBase.java b/core/src/main/java/org/powermock/core/spi/support/AbstractPowerMockTestListenerBase.java
new file mode 100644
index 0000000..cd6bd65
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/support/AbstractPowerMockTestListenerBase.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.support;
+
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+
+import java.lang.reflect.Method;
+
+/**
+ * An empty implementation of the {@link PowerMockTestListener} interface. May
+ * be inherited by clients that wants to provide empty implementations of some
+ * of the interface methods.
+ */
+public class AbstractPowerMockTestListenerBase implements PowerMockTestListener {
+
+ /**
+ * Provides an empty implementation.
+ */
+ @Override
+ public void afterTestMethod(Object testInstance, Method method, Object[] arguments, TestMethodResult testResult) throws Exception {
+ }
+
+ /**
+ * Provides an empty implementation.
+ */
+ @Override
+ public void beforeTestMethod(Object testInstance, Method method, Object[] arguments) throws Exception {
+ }
+
+ /**
+ * Provides an empty implementation.
+ */
+ @Override
+ public void beforeTestSuiteStarted(Class<?> testClass, Method[] testMethods) throws Exception {
+ }
+
+ /**
+ * Provides an empty implementation.
+ */
+ @Override
+ public void afterTestSuiteEnded(Class<?> testClass, Method[] methods, TestSuiteResult testResult) throws Exception {
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/spi/support/InvocationSubstitute.java b/core/src/main/java/org/powermock/core/spi/support/InvocationSubstitute.java
new file mode 100644
index 0000000..82a3b91
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/support/InvocationSubstitute.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.support;
+
+/**
+ * A class that can be used as a substitution instead of mocking a particular
+ * class. For example when mocking a new instance call you can fake the
+ * constructor invocation by creating a mock object (A) for this class and
+ * invoke the {@link #performSubstitutionLogic(Object...)} method instead with
+ * the constructor arguments. The interception process must take care of doing
+ * this. Also remember that behaviors such as replay and/or verify must be
+ * performed on (A).
+ *
+ */
+public interface InvocationSubstitute<T> {
+
+ public T performSubstitutionLogic(Object... arguments) throws Exception;
+}
diff --git a/core/src/main/java/org/powermock/core/spi/testresult/Result.java b/core/src/main/java/org/powermock/core/spi/testresult/Result.java
new file mode 100644
index 0000000..ee9c24d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/testresult/Result.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.testresult;
+
+public enum Result {
+ SUCCESSFUL, FAILED, IGNORED;
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/powermock/core/spi/testresult/TestMethodResult.java b/core/src/main/java/org/powermock/core/spi/testresult/TestMethodResult.java
new file mode 100644
index 0000000..631a562
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/testresult/TestMethodResult.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.testresult;
+
+public interface TestMethodResult {
+
+ Result getResult();
+}
diff --git a/core/src/main/java/org/powermock/core/spi/testresult/TestSuiteResult.java b/core/src/main/java/org/powermock/core/spi/testresult/TestSuiteResult.java
new file mode 100644
index 0000000..a17d227
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/testresult/TestSuiteResult.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.testresult;
+
+public interface TestSuiteResult {
+
+ int getTestCount();
+
+ int getIgnoreCount();
+
+ int getSuccessCount();
+
+ int getFailureCount();
+
+ Result getResult();
+}
diff --git a/core/src/main/java/org/powermock/core/spi/testresult/impl/TestMethodResultImpl.java b/core/src/main/java/org/powermock/core/spi/testresult/impl/TestMethodResultImpl.java
new file mode 100644
index 0000000..6a54718
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/testresult/impl/TestMethodResultImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.testresult.impl;
+
+import org.powermock.core.spi.testresult.Result;
+import org.powermock.core.spi.testresult.TestMethodResult;
+
+public class TestMethodResultImpl implements TestMethodResult {
+
+ private final Result result;
+
+ public TestMethodResultImpl(Result result) {
+ super();
+ this.result = result;
+ }
+
+ @Override
+ public Result getResult() {
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return result.toString();
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/spi/testresult/impl/TestSuiteResultImpl.java b/core/src/main/java/org/powermock/core/spi/testresult/impl/TestSuiteResultImpl.java
new file mode 100644
index 0000000..83c9301
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/spi/testresult/impl/TestSuiteResultImpl.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.spi.testresult.impl;
+
+import org.powermock.core.spi.testresult.Result;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+
+public class TestSuiteResultImpl implements TestSuiteResult {
+
+ private int failureCount;
+
+ private int successCount;
+
+ private int testCount;
+
+ private int ignoreCount;
+
+ public TestSuiteResultImpl() {
+ }
+
+ public TestSuiteResultImpl(int failureCount, int successCount, int testCount, int ignoreCount) {
+ this.failureCount = failureCount;
+ this.successCount = successCount;
+ this.testCount = testCount;
+ this.ignoreCount = ignoreCount;
+ }
+
+ @Override
+ public int getFailureCount() {
+ return failureCount;
+ }
+
+ @Override
+ public int getSuccessCount() {
+ return successCount;
+ }
+
+ @Override
+ public int getIgnoreCount() {
+ return ignoreCount;
+ }
+
+ @Override
+ public Result getResult() {
+ Result result = Result.SUCCESSFUL;
+ if (testCount == 0) {
+ result = Result.IGNORED;
+ } else if (failureCount != 0) {
+ result = Result.FAILED;
+ }
+ return result;
+ }
+
+ @Override
+ public int getTestCount() {
+ return testCount;
+ }
+
+ @Override
+ public String toString() {
+ return getResult().toString();
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/testlisteners/FieldDefaulter.java b/core/src/main/java/org/powermock/core/testlisteners/FieldDefaulter.java
new file mode 100644
index 0000000..7952f5e
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/testlisteners/FieldDefaulter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.testlisteners;
+
+import org.powermock.core.spi.support.AbstractPowerMockTestListenerBase;
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.internal.TypeUtils;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * A test listener that automatically set all instance fields to their default
+ * values after each test method. E.g. an object field is set to
+ * <code>null</code>, an <code>int</code> field is set to 0 and so on.
+ */
+public class FieldDefaulter extends AbstractPowerMockTestListenerBase {
+
+ @Override
+ public void afterTestMethod(Object testInstance, Method method, Object[] arguments, TestMethodResult testResult) throws Exception {
+ Set<Field> allFields = Whitebox.getAllInstanceFields(testInstance);
+ for (Field field : allFields) {
+ field.set(testInstance, TypeUtils.getDefaultValue(field.getType()));
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupport.java b/core/src/main/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupport.java
new file mode 100644
index 0000000..e4f453d
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupport.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.testlisteners;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Core static utility to help modules, such as PowerMockRunner, that needs to
+ * communicate with some 3rd-party framework in order to properly fire
+ * events to PowerMockTestListener instances.
+ */
+public class GlobalNotificationBuildSupport {
+
+ public interface Callback {
+ void suiteClassInitiated(Class<?> testClass);
+
+ void testInstanceCreated(Object testInstance);
+ }
+
+ private static final Map<String, Callback> testSuiteCallbacks =
+ new ConcurrentHashMap<String, Callback>();
+
+ private static final Map<Class<?>, Callback> initiatedTestSuiteClasses =
+ new ConcurrentHashMap<Class<?>, Callback>();
+
+ private static final ThreadLocal<Class<?>> pendingInitiatedTestClass =
+ new ThreadLocal<Class<?>>();
+
+ public static void prepareTestSuite(
+ String testClassName, Callback callback) {
+ if (testSuiteCallbacks.containsKey(testClassName)) {
+ throw new IllegalStateException(
+ "Needs to wait for concurrent test-suite execution to start!");
+ } else {
+ testSuiteCallbacks.put(testClassName, callback);
+ Class<?> initiatedTestClass = pendingInitiatedTestClass.get();
+ if (null != initiatedTestClass
+ && initiatedTestClass.getName().equals(testClassName)) {
+ System.err.println("Detected late test-suite preparation of "
+ + "already initiated test-" + initiatedTestClass);
+ testClassInitiated(initiatedTestClass);
+ }
+ }
+ }
+
+ public static void testClassInitiated(Class<?> testClass) {
+ if (!initiatedTestSuiteClasses.containsKey(testClass)) {
+ Callback callback = testSuiteCallbacks.get(testClass.getName());
+ if (null == callback) {
+ pendingInitiatedTestClass.set(testClass);
+ } else {
+ initiatedTestSuiteClasses.put(testClass, callback);
+ callback.suiteClassInitiated(testClass);
+ pendingInitiatedTestClass.set(null);
+ }
+ }
+ }
+
+ private static int countInitializersInTrace(final String className) {
+ int initializerCount = 0;
+ for (StackTraceElement ste : new Throwable().getStackTrace()) {
+ if ("<init>".equals(ste.getMethodName())
+ && className.equals(ste.getClassName())
+ && 2 <= ++initializerCount) {
+ return 2;
+ }
+ }
+ return initializerCount;
+ }
+
+ public static void testInstanceCreated(Object testInstance) {
+ for (Class<?> c = testInstance.getClass(); Object.class != c; c = c.getSuperclass()) {
+ Callback callback = initiatedTestSuiteClasses.get(c);
+ if (null != callback) {
+ if (1 == countInitializersInTrace(c.getName())) {
+ callback.testInstanceCreated(testInstance);
+ }
+ return;
+ }
+ }
+ }
+
+ public static void closeTestSuite(Class<?> testClass) {
+ Callback callback = initiatedTestSuiteClasses.remove(testClass);
+ if (null != callback
+ && !initiatedTestSuiteClasses.values().contains(callback)) {
+ testSuiteCallbacks.values().remove(callback);
+ }
+ }
+
+ public static void closePendingTestSuites(Callback callback) {
+ testSuiteCallbacks.values().remove(callback);
+ initiatedTestSuiteClasses.values()
+ .removeAll(java.util.Collections.singleton(callback));
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/MockTransformer.java b/core/src/main/java/org/powermock/core/transformers/MockTransformer.java
new file mode 100644
index 0000000..a37f0e8
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/MockTransformer.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.core.transformers;
+
+import javassist.CtClass;
+
+/**
+ * Interface that all mock transformers must implement. The purpose of a mock
+ * transformer is to create a modified version of a <code>Class</code> so that
+ * it is mock enabled.
+ *
+ * @author Johan Haleby
+ */
+public interface MockTransformer {
+
+ /**
+ * Transforms the <code>clazz</code>.
+ *
+ * @param clazz
+ * The class to be
+ * transform into a mock enabled class.
+ * @return A <code>CtClass</code> representation of the mocked class.
+ */
+ public CtClass transform(CtClass clazz) throws Exception;
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/TransformStrategy.java b/core/src/main/java/org/powermock/core/transformers/TransformStrategy.java
new file mode 100644
index 0000000..cb89343
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/TransformStrategy.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.transformers;
+
+public enum TransformStrategy {
+ CLASSLOADER, INST_REDEFINE, INST_TRANSFORM;
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/impl/AbstractMainMockTransformer.java b/core/src/main/java/org/powermock/core/transformers/impl/AbstractMainMockTransformer.java
new file mode 100644
index 0000000..9ae78f7
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/impl/AbstractMainMockTransformer.java
@@ -0,0 +1,439 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.transformers.impl;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import javassist.bytecode.AttributeInfo;
+import javassist.bytecode.ClassFile;
+import javassist.bytecode.CodeAttribute;
+import javassist.bytecode.DuplicateMemberException;
+import javassist.bytecode.InnerClassesAttribute;
+import javassist.expr.ConstructorCall;
+import javassist.expr.ExprEditor;
+import javassist.expr.FieldAccess;
+import javassist.expr.MethodCall;
+import javassist.expr.NewExpr;
+import org.powermock.core.IndicateReloadClass;
+import org.powermock.core.MockGateway;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.TransformStrategy;
+
+import static org.powermock.core.transformers.TransformStrategy.CLASSLOADER;
+import static org.powermock.core.transformers.TransformStrategy.INST_REDEFINE;
+import static org.powermock.core.transformers.TransformStrategy.INST_TRANSFORM;
+
+/**
+ *
+ */
+public abstract class AbstractMainMockTransformer implements MockTransformer {
+
+ private static final String VOID = "";
+ private static final int METHOD_CODE_LENGTH_LIMIT = 65536;
+ protected final TransformStrategy strategy;
+
+ public AbstractMainMockTransformer(TransformStrategy strategy) {this.strategy = strategy;}
+
+ protected String allowMockingOfPackagePrivateClasses(final CtClass clazz) {
+ final String name = clazz.getName();
+ if (strategy != INST_REDEFINE) {
+ try {
+ final int modifiers = clazz.getModifiers();
+ if (Modifier.isPackage(modifiers)) {
+ if (!name.startsWith("java.") && !(clazz.isInterface() && clazz.getDeclaringClass() != null)) {
+ clazz.setModifiers(Modifier.setPublic(modifiers));
+ }
+ }
+ } catch (NotFoundException e) {
+ // OK, continue
+ }
+ }
+ return name;
+ }
+
+ protected void suppressStaticInitializerIfRequested(final CtClass clazz, final String name) throws CannotCompileException {
+ if (strategy == CLASSLOADER) {
+ if (MockGateway.staticConstructorCall(name) != MockGateway.PROCEED) {
+ CtConstructor classInitializer = clazz.makeClassInitializer();
+ classInitializer.setBody("{}");
+ }
+ }
+ }
+
+ protected void removeFinalModifierFromClass(final CtClass clazz) {
+ if (strategy != INST_REDEFINE) {
+ if (Modifier.isFinal(clazz.getModifiers())) {
+ clazz.setModifiers(clazz.getModifiers() ^ Modifier.FINAL);
+ }
+
+ ClassFile classFile = clazz.getClassFile2();
+ AttributeInfo attribute = classFile.getAttribute(InnerClassesAttribute.tag);
+ if (attribute != null && attribute instanceof InnerClassesAttribute) {
+ InnerClassesAttribute ica = (InnerClassesAttribute) attribute;
+ String name = classFile.getName();
+ int n = ica.tableLength();
+ for (int i = 0; i < n; ++i) {
+ if (name.equals(ica.innerClass(i))) {
+ int accessFlags = ica.accessFlags(i);
+ if (Modifier.isFinal(accessFlags)) {
+ ica.setAccessFlags(i, accessFlags ^ Modifier.FINAL);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ protected void allowMockingOfStaticAndFinalAndNativeMethods(final CtClass clazz) throws NotFoundException, CannotCompileException {
+ if (strategy != INST_TRANSFORM) {
+ for (CtMethod m : clazz.getDeclaredMethods()) {
+ modifyMethod(m);
+ }
+ }
+ }
+
+ protected void removeFinalModifierFromAllStaticFinalFields(final CtClass clazz) {
+ if (strategy != INST_REDEFINE) {
+ for (CtField f : clazz.getDeclaredFields()) {
+ final int modifiers = f.getModifiers();
+ if (Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers)) {
+ f.setModifiers(modifiers ^ Modifier.FINAL);
+ }
+ }
+ }
+ }
+
+ protected void setAllConstructorsToPublic(final CtClass clazz) {
+ if (strategy == CLASSLOADER) {
+ for (CtConstructor c : clazz.getDeclaredConstructors()) {
+ final int modifiers = c.getModifiers();
+ if (!Modifier.isPublic(modifiers)) {
+ c.setModifiers(Modifier.setPublic(modifiers));
+ }
+ }
+ }
+ }
+
+ /**
+ * According to JVM specification method size must be lower than 65536 bytes.
+ * When that limit is exceeded class loader will fail to load the class.
+ * Since instrumentation can increase method size significantly it must be
+ * ensured that JVM limit is not exceeded.
+ * <p>
+ * When the limit is exceeded method's body is replaced by exception throw.
+ * Method is then instrumented again to allow mocking and suppression.
+ *
+ * @see <a href="http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3">JVM specification</a>
+ */
+ protected CtClass ensureJvmMethodSizeLimit(CtClass clazz) throws CannotCompileException, NotFoundException {
+ for (CtMethod method : clazz.getDeclaredMethods()) {
+ if (isMethodSizeExceeded(method)) {
+ String code = "{throw new IllegalAccessException(\"" +
+ "Method was too large and after instrumentation exceeded JVM limit. " +
+ "PowerMock modified the method to allow JVM to load the class. " +
+ "You can use PowerMock API to suppress or mock this method behaviour." +
+ "\");}";
+ method.setBody(code);
+ modifyMethod(method);
+ }
+ }
+ return clazz;
+ }
+
+ private boolean isMethodSizeExceeded(CtMethod method) {
+ CodeAttribute codeAttribute = method.getMethodInfo().getCodeAttribute();
+ return codeAttribute != null && codeAttribute.getCodeLength() >= METHOD_CODE_LENGTH_LIMIT;
+ }
+
+ private void modifyMethod(final CtMethod method) throws NotFoundException, CannotCompileException {
+ if (!Modifier.isAbstract(method.getModifiers())) {
+ // Lookup the method return type
+ final CtClass returnTypeAsCtClass = method.getReturnType();
+ final String returnTypeAsString = getReturnTypeAsString(method);
+
+ if (Modifier.isNative(method.getModifiers())) {
+ String methodName = method.getName();
+ String returnValue = "($r)value";
+
+ if (returnTypeAsCtClass.equals(CtClass.voidType)) {
+ returnValue = VOID;
+ }
+
+ String classOrInstance = "this";
+ if (Modifier.isStatic(method.getModifiers())) {
+ classOrInstance = "$class";
+ }
+ method.setModifiers(method.getModifiers() - Modifier.NATIVE);
+ String code = "Object value = " + MockGateway.class.getName() + ".methodCall(" + classOrInstance + ", \"" + method.getName()
+ + "\", $args, $sig, \"" + returnTypeAsString + "\");" + "if (value != " + MockGateway.class.getName() + ".PROCEED) "
+ + "return " + returnValue + "; " + "throw new java.lang.UnsupportedOperationException(\"" + methodName + " is native\");";
+ method.setBody("{" + code + "}");
+ return;
+ }
+
+ final String returnValue = getCorrectReturnValueType(returnTypeAsCtClass);
+
+ String classOrInstance = "this";
+ if (Modifier.isStatic(method.getModifiers())) {
+ classOrInstance = "$class";
+ }
+
+ String code = "Object value = " + MockGateway.class.getName() + ".methodCall(" + classOrInstance + ", \"" + method.getName()
+ + "\", $args, $sig, \"" + returnTypeAsString + "\");" + "if (value != " + MockGateway.class.getName() + ".PROCEED) " + "return "
+ + returnValue + "; ";
+
+ method.insertBefore("{ " + code + "}");
+ }
+ }
+
+ private String getReturnTypeAsString(final CtMethod method) throws NotFoundException {
+ CtClass returnType = method.getReturnType();
+ String returnTypeAsString = VOID;
+ if (!returnType.equals(CtClass.voidType)) {
+ returnTypeAsString = returnType.getName();
+ }
+ return returnTypeAsString;
+ }
+
+ /**
+ * @return The correct return type, i.e. takes care of casting the a wrapper
+ * type to primitive type if needed.
+ */
+ private String getCorrectReturnValueType(final CtClass returnTypeAsCtClass) {
+ final String returnTypeAsString = returnTypeAsCtClass.getName();
+ final String returnValue;
+ if (returnTypeAsCtClass.equals(CtClass.voidType)) {
+ returnValue = VOID;
+ } else if (returnTypeAsCtClass.isPrimitive()) {
+ if (returnTypeAsString.equals("char")) {
+ returnValue = "((java.lang.Character)value).charValue()";
+ } else if (returnTypeAsString.equals("boolean")) {
+ returnValue = "((java.lang.Boolean)value).booleanValue()";
+ } else {
+ returnValue = "((java.lang.Number)value)." + returnTypeAsString + "Value()";
+ }
+ } else {
+ returnValue = "(" + returnTypeAsString + ")value";
+ }
+ return returnValue;
+ }
+
+ public CtClass transform(final CtClass clazz) throws Exception {
+ if (clazz.isFrozen()) {
+ clazz.defrost();
+ }
+ return transformMockClass(clazz);
+
+
+ }
+
+ protected abstract CtClass transformMockClass(CtClass clazz) throws CannotCompileException, NotFoundException;
+
+ protected final class PowerMockExpressionEditor extends ExprEditor {
+ private final CtClass clazz;
+
+ protected PowerMockExpressionEditor(CtClass clazz) {
+ this.clazz = clazz;
+ }
+
+ @Override
+ public void edit(FieldAccess f) throws CannotCompileException {
+ if (f.isReader()) {
+ CtClass returnTypeAsCtClass;
+
+ try {
+ returnTypeAsCtClass = f.getField().getType();
+ } catch (NotFoundException e) {
+ /*
+ * If multiple java agents are active (in INST_REDEFINE mode), the types implicitly loaded by javassist from disk
+ * might differ from the types available in memory. Thus, this error might occur.
+ *
+ * It may also happen if PowerMock is modifying an SPI where the SPI require some classes to be available in the classpath
+ * at runtime but they are not! This is valid in some cases such as slf4j.
+ */
+ return;
+ }
+ StringBuilder code = new StringBuilder();
+ code.append("{Object value = ").append(MockGateway.class.getName()).append(".fieldCall(").append("$0,$class,\"").append(
+ f.getFieldName()).append("\",$type);");
+ code.append("if(value == ").append(MockGateway.class.getName()).append(".PROCEED) {");
+ code.append(" $_ = $proceed($$);");
+ code.append("} else {");
+ code.append(" $_ = ").append(getCorrectReturnValueType(returnTypeAsCtClass)).append(";");
+ code.append("}}");
+ f.replace(code.toString());
+ }
+ }
+
+ @Override
+ public void edit(MethodCall m) throws CannotCompileException {
+ try {
+ final CtMethod method = m.getMethod();
+ final CtClass declaringClass = method.getDeclaringClass();
+ if (declaringClass != null) {
+ if (shouldTreatAsSystemClassCall(declaringClass)) {
+ StringBuilder code = new StringBuilder();
+ code.append("{Object classOrInstance = null; if($0!=null){classOrInstance = $0;} else { classOrInstance = $class;}");
+ code.append("Object value = ").append(MockGateway.class.getName()).append(".methodCall(").append("classOrInstance,\"")
+ .append(m.getMethodName()).append("\",$args, $sig,\"").append(getReturnTypeAsString(method)).append("\");");
+ code.append("if(value == ").append(MockGateway.class.getName()).append(".PROCEED) {");
+ code.append(" $_ = $proceed($$);");
+ code.append("} else {");
+ final String correctReturnValueType = getCorrectReturnValueType(method.getReturnType());
+ if (!VOID.equals(correctReturnValueType)) {
+ code.append(" $_ = ").append(correctReturnValueType).append(";");
+ }
+ code.append("}}");
+ m.replace(code.toString());
+ }
+ }
+ } catch (NotFoundException e) {
+ /*
+ * If multiple java agents are active (in INST_REDEFINE mode), the types implicitly loaded by javassist from disk
+ * might differ from the types available in memory. Thus, this error might occur.
+ *
+ * It may also happen if PowerMock is modifying an SPI where the SPI require some classes to be available in the classpath
+ * at runtime but they are not! This is valid in some cases such as slf4j.
+ */
+ }
+ }
+
+ private boolean shouldTreatAsSystemClassCall(CtClass declaringClass) {
+ final String className = declaringClass.getName();
+ return className.startsWith("java.");
+ }
+
+ @Override
+ public void edit(ConstructorCall c) throws CannotCompileException {
+ /*
+ * Note that constructor call only intercepts calls to super or this
+ * from an instantiated class. This means that A a = new A(); will
+ * NOT trigger a ConstructorCall for the default constructor in A.
+ * If A where to extend B and A's constructor only delegates to
+ * super(), the default constructor of B would trigger a
+ * ConstructorCall. This means that we need to handle
+ * "suppressConstructorCode" both here and in NewExpr.
+ */
+ if (strategy != INST_REDEFINE && !c.getClassName().startsWith("java.lang")) {
+ final CtClass superclass;
+ try {
+ superclass = clazz.getSuperclass();
+ } catch (NotFoundException e) {
+ throw new RuntimeException(e);
+ }
+
+ /*
+ * Create a default constructor in the super class if it doesn't
+ * exist. This is needed because if the code in the current
+ * constructor should be suppressed (which we don't know at this
+ * moment of time) the parent class must have a default
+ * constructor that we can delegate to.
+ */
+ addNewDeferConstructor(clazz);
+ final StringBuilder code = new StringBuilder();
+ code.append("{Object value =").append(MockGateway.class.getName()).append(".constructorCall($class, $args, $sig);");
+ code.append("if (value != ").append(MockGateway.class.getName()).append(".PROCEED){");
+
+ /*
+ * TODO Suppress and lazy inject field (when this feature is ready).
+ */
+ if (superclass.getName().equals(Object.class.getName())) {
+ code.append(" super();");
+ } else {
+ code.append(" super((" + IndicateReloadClass.class.getName() + ") null);");
+ }
+ code.append("} else {");
+ code.append(" $proceed($$);");
+ code.append("}}");
+ c.replace(code.toString());
+ }
+ }
+
+ /**
+ * Create a defer constructor in the class which will be called when the
+ * constructor is suppressed.
+ *
+ * @param clazz The class whose super constructor will get a new defer
+ * constructor if it doesn't already have one.
+ * @throws CannotCompileException If an unexpected compilation error occurs.
+ */
+ private void addNewDeferConstructor(final CtClass clazz) throws CannotCompileException {
+ final CtClass superClass;
+ try {
+ superClass = clazz.getSuperclass();
+ } catch (NotFoundException e1) {
+ throw new IllegalArgumentException("Internal error: Failed to get superclass for " + clazz.getName()
+ + " when about to create a new default constructor.");
+ }
+
+ ClassPool classPool = clazz.getClassPool();
+ /*
+ * To make a unique defer constructor we create a new constructor
+ * with one argument (IndicateReloadClass). So we get this class a
+ * Javassist class below.
+ */
+ final CtClass constructorType;
+ try {
+ constructorType = classPool.get(IndicateReloadClass.class.getName());
+ } catch (NotFoundException e) {
+ throw new IllegalArgumentException("Internal error: failed to get the " + IndicateReloadClass.class.getName()
+ + " when added defer constructor.");
+ }
+ clazz.defrost();
+ if (superClass.getName().equals(Object.class.getName())) {
+ try {
+ clazz.addConstructor(CtNewConstructor.make(new CtClass[]{constructorType}, new CtClass[0], "{super();}", clazz));
+ } catch (DuplicateMemberException e) {
+ // OK, the constructor has already been added.
+ }
+ } else {
+ addNewDeferConstructor(superClass);
+ try {
+ clazz.addConstructor(CtNewConstructor.make(new CtClass[]{constructorType}, new CtClass[0], "{super($$);}", clazz));
+ } catch (DuplicateMemberException e) {
+ // OK, the constructor has already been added.
+ }
+ }
+ }
+
+ @Override
+ public void edit(NewExpr e) throws CannotCompileException {
+ final StringBuilder code = new StringBuilder();
+ code.append("Object instance =").append(MockGateway.class.getName()).append(".newInstanceCall($type,$args,$sig);");
+ code.append("if(instance != ").append(MockGateway.class.getName()).append(".PROCEED) {");
+ code.append(" if(instance instanceof java.lang.reflect.Constructor) {");
+ // TODO Change to objenisis instead
+ code
+ .append(" $_ = ($r) sun.reflect.ReflectionFactory.getReflectionFactory().newConstructorForSerialization($type, java.lang.Object.class.getDeclaredConstructor(null)).newInstance(null);");
+ code.append(" } else {");
+ code.append(" $_ = ($r) instance;");
+ code.append(" }");
+ code.append("} else {");
+ code.append(" $_ = $proceed($$);");
+ code.append("}");
+ e.replace(code.toString());
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/impl/ClassMockTransformer.java b/core/src/main/java/org/powermock/core/transformers/impl/ClassMockTransformer.java
new file mode 100644
index 0000000..250512f
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/impl/ClassMockTransformer.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.core.transformers.impl;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import org.powermock.core.transformers.TransformStrategy;
+
+import static org.powermock.core.transformers.TransformStrategy.CLASSLOADER;
+import static org.powermock.core.transformers.TransformStrategy.INST_TRANSFORM;
+
+public class ClassMockTransformer extends AbstractMainMockTransformer {
+
+ public ClassMockTransformer() {
+ this(CLASSLOADER);
+ }
+
+ public ClassMockTransformer(TransformStrategy strategy) {
+ super(strategy);
+ }
+
+ @Override
+ protected CtClass transformMockClass(CtClass clazz) throws CannotCompileException, NotFoundException {
+ if (clazz.isInterface()) {
+ return clazz;
+ }
+
+ /*
+ * Set class modifier to public to allow for mocking of package private
+ * classes. This is needed because we've changed to CgLib naming policy
+ * to allow for mocking of signed classes.
+ */
+
+ final String name = allowMockingOfPackagePrivateClasses(clazz);
+
+ suppressStaticInitializerIfRequested(clazz, name);
+
+ // This should probably be configurable
+ removeFinalModifierFromClass(clazz);
+
+ allowMockingOfStaticAndFinalAndNativeMethods(clazz);
+
+ // Convert all constructors to public
+ setAllConstructorsToPublic(clazz);
+
+ // Remove final from all static final fields. Not possible if using a java agent.
+ removeFinalModifierFromAllStaticFinalFields(clazz);
+
+ if (strategy != INST_TRANSFORM) {
+ clazz.instrument(new PowerMockExpressionEditor(clazz));
+ }
+
+ ensureJvmMethodSizeLimit(clazz);
+
+ return clazz;
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/impl/InterfaceMockTransformer.java b/core/src/main/java/org/powermock/core/transformers/impl/InterfaceMockTransformer.java
new file mode 100644
index 0000000..5ef957e
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/impl/InterfaceMockTransformer.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.core.transformers.impl;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.NotFoundException;
+import org.powermock.core.transformers.TransformStrategy;
+
+import static org.powermock.core.transformers.TransformStrategy.CLASSLOADER;
+import static org.powermock.core.transformers.TransformStrategy.INST_TRANSFORM;
+
+/**
+ *
+ */
+public class InterfaceMockTransformer extends AbstractMainMockTransformer {
+
+ public InterfaceMockTransformer() {
+ this(CLASSLOADER);
+ }
+
+ public InterfaceMockTransformer(TransformStrategy strategy) {
+ super(strategy);
+ }
+
+ @Override
+ protected CtClass transformMockClass(CtClass clazz) throws CannotCompileException, NotFoundException {
+ if (!clazz.isInterface()) {
+ return clazz;
+ }
+
+ /*
+ * Set class modifier to public to allow for mocking of package private
+ * classes. This is needed because we've changed to CgLib naming policy
+ * to allow for mocking of signed classes.
+ */
+
+ final String name = allowMockingOfPackagePrivateClasses(clazz);
+
+ suppressStaticInitializerIfRequested(clazz, name);
+
+ allowMockingOfStaticAndFinalAndNativeMethods(clazz);
+
+ if (strategy != INST_TRANSFORM) {
+ clazz.instrument(new PowerMockExpressionEditor(clazz));
+ }
+
+ ensureJvmMethodSizeLimit(clazz);
+
+ return clazz;
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/impl/Primitives.java b/core/src/main/java/org/powermock/core/transformers/impl/Primitives.java
new file mode 100644
index 0000000..606ec21
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/impl/Primitives.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.transformers.impl;
+
+import java.util.Collections;
+import java.util.IdentityHashMap;
+import java.util.Map;
+import javassist.CtPrimitiveType;
+
+import static javassist.CtClass.*;
+
+/**
+ * Simple utility that maps constant fields of {@link javassist.CtClass} to
+ * their corresponding java class-objects for primitive types.
+ */
+class Primitives {
+
+ private static final Map<CtPrimitiveType,Class<?>> ct2primitiveClass =
+ lookupMappings();
+
+ static Class<?> getClassFor(CtPrimitiveType ctPrimitiveType) {
+ return ct2primitiveClass.get(ctPrimitiveType);
+ }
+
+ private static Map<CtPrimitiveType, Class<?>> lookupMappings() {
+ Map<CtPrimitiveType,Class<?>> mappings = new IdentityHashMap<CtPrimitiveType, Class<?>>(10);
+ for (Object[] each : new Object[][] {
+ {booleanType, boolean.class},
+ {byteType, byte.class},
+ {charType, char.class},
+ {doubleType, double.class},
+ {floatType, float.class},
+ {intType, int.class},
+ {longType, long.class},
+ {shortType, short.class},
+ {voidType, void.class}
+ }) {
+ mappings.put( (CtPrimitiveType)each[0], (Class<?>)each[1]);
+ }
+ return Collections.unmodifiableMap(mappings);
+ }
+}
diff --git a/core/src/main/java/org/powermock/core/transformers/impl/TestClassTransformer.java b/core/src/main/java/org/powermock/core/transformers/impl/TestClassTransformer.java
new file mode 100644
index 0000000..ec56dfa
--- /dev/null
+++ b/core/src/main/java/org/powermock/core/transformers/impl/TestClassTransformer.java
@@ -0,0 +1,342 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.core.transformers.impl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.HashSet;
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtMethod;
+import javassist.CtPrimitiveType;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import javassist.bytecode.AnnotationsAttribute;
+import org.powermock.core.IndicateReloadClass;
+import org.powermock.core.testlisteners.GlobalNotificationBuildSupport;
+import org.powermock.core.transformers.MockTransformer;
+
+/**
+ * MockTransformer implementation that will make PowerMock test-class
+ * enhancements for four purposes...
+ * 1) Make test-class static initializer and constructor send crucial details
+ * (for PowerMockTestListener events) to GlobalNotificationBuildSupport so that
+ * this information can be forwarded to whichever
+ * facility is used for composing the PowerMockTestListener events.
+ * 2) Removal of test-method annotations as a mean to achieve test-suite
+ * chunking!
+ * 3) Restore original test-class constructors` accesses
+ * (in case they have all been made public by {@link
+ * ClassMockTransformer#setAllConstructorsToPublic(javassist.CtClass)})
+ * - to avoid that multiple <i>public</i> test-class constructors cause
+ * a delegate runner from JUnit (or 3rd party) to bail out with an
+ * error message such as "Test class can only have one constructor".
+ * 4) Set test-class defer constructor (if exist) as protected instead of public.
+ * Otherwise a delegate runner from JUnit (or 3rd party) might get confused by
+ * the presence of more than one test-class constructor and bail out with an
+ * error message such as "Test class can only have one constructor".
+ *
+ * The #3 and #4 enhancements will also be enforced on the constructors
+ * of classes that are nested within the test-class.
+ */
+public abstract class TestClassTransformer implements MockTransformer {
+
+ private final Class<?> testClass;
+ private final Class<? extends Annotation> testMethodAnnotationType;
+
+ public interface ForTestClass {
+ RemovesTestMethodAnnotation removesTestMethodAnnotation(Class<? extends Annotation> testMethodAnnotation);
+
+ public interface RemovesTestMethodAnnotation {
+ TestClassTransformer fromMethods(Collection<Method> testMethodsThatRunOnOtherClassLoaders);
+ TestClassTransformer fromAllMethodsExcept(Method singleMethodToRunOnThisClassLoader);
+ }
+ }
+
+ public static ForTestClass forTestClass(final Class<?> testClass) {
+ return new ForTestClass() {
+ @Override
+ public RemovesTestMethodAnnotation removesTestMethodAnnotation(
+ final Class<? extends Annotation> testMethodAnnotation) {
+ return new RemovesTestMethodAnnotation() {
+
+ @Override
+ public TestClassTransformer fromMethods(
+ final Collection<Method> testMethodsThatRunOnOtherClassLoaders) {
+ return new TestClassTransformer(testClass, testMethodAnnotation) {
+ /**
+ * Is lazily initilized because of
+ * AbstractTestSuiteChunkerImpl#chunkClass(Class)
+ */
+ Collection<String> methodsThatRunOnOtherClassLoaders;
+ @Override
+ boolean mustHaveTestAnnotationRemoved(CtMethod method)
+ throws NotFoundException {
+ if (null == methodsThatRunOnOtherClassLoaders) {
+ /* This lazy initialization is necessary - see above */
+ methodsThatRunOnOtherClassLoaders = new HashSet<String>();
+ for (Method m : testMethodsThatRunOnOtherClassLoaders) {
+ methodsThatRunOnOtherClassLoaders.add(
+ signatureOf(m));
+ }
+ testMethodsThatRunOnOtherClassLoaders.clear();
+ }
+ return methodsThatRunOnOtherClassLoaders
+ .contains(signatureOf(method));
+ }
+ };
+ }
+
+ @Override
+ public TestClassTransformer fromAllMethodsExcept(
+ Method singleMethodToRunOnTargetClassLoader) {
+ final String targetMethodSignature =
+ signatureOf(singleMethodToRunOnTargetClassLoader);
+ return new TestClassTransformer(testClass, testMethodAnnotation) {
+ @Override
+ boolean mustHaveTestAnnotationRemoved(CtMethod method)
+ throws Exception {
+ return false == signatureOf(method)
+ .equals(targetMethodSignature);
+ }
+ };
+ }
+ };
+ }
+ };
+ }
+
+ private TestClassTransformer(
+ Class<?> testClass, Class<? extends Annotation> testMethodAnnotationType) {
+ this.testClass = testClass;
+ this.testMethodAnnotationType = testMethodAnnotationType;
+ }
+
+ private boolean isTestClass(CtClass clazz) {
+ try {
+ return Class.forName(clazz.getName(), false, testClass.getClassLoader())
+ .isAssignableFrom(testClass);
+ } catch (ClassNotFoundException ex) {
+ return false;
+ }
+ }
+
+ private boolean isNestedWithinTestClass(CtClass clazz) {
+ String clazzName = clazz.getName();
+ return clazzName.startsWith(testClass.getName())
+ && '$' == clazzName.charAt(testClass.getName().length());
+ }
+
+ private Class<?> asOriginalClass(CtClass type) throws Exception {
+ try {
+ return type.isArray()
+ ? Array.newInstance(asOriginalClass(type.getComponentType()), 0).getClass()
+ : type.isPrimitive()
+ ? Primitives.getClassFor((CtPrimitiveType) type)
+ : Class.forName(type.getName(), true, testClass.getClassLoader());
+ } catch (Exception ex) {
+ throw new RuntimeException("Cannot resolve type: " + type, ex);
+ }
+ }
+
+ private Class<?>[] asOriginalClassParams(CtClass[] parameterTypes)
+ throws Exception {
+ final Class<?>[] classParams = new Class[parameterTypes.length];
+ for (int i = 0; i < classParams.length; ++i) {
+ classParams[i] = asOriginalClass(parameterTypes[i]);
+ }
+ return classParams;
+ }
+
+ abstract boolean mustHaveTestAnnotationRemoved(CtMethod method) throws Exception;
+
+ private void removeTestMethodAnnotationFrom(CtMethod m)
+ throws ClassNotFoundException {
+ final AnnotationsAttribute attr = (AnnotationsAttribute)
+ m.getMethodInfo().getAttribute(AnnotationsAttribute.visibleTag);
+ javassist.bytecode.annotation.Annotation[] newAnnotations =
+ new javassist.bytecode.annotation.Annotation[attr.numAnnotations() - 1];
+ int i = -1;
+ for (javassist.bytecode.annotation.Annotation a : attr.getAnnotations()) {
+ if (a.getTypeName().equals(testMethodAnnotationType.getName())) {
+ continue;
+ }
+ newAnnotations[++i] = a;
+ }
+ attr.setAnnotations(newAnnotations);
+ }
+
+ private void removeTestAnnotationsForTestMethodsThatRunOnOtherClassLoader(CtClass clazz)
+ throws Exception {
+ for (CtMethod m : clazz.getDeclaredMethods()) {
+ if (m.hasAnnotation(testMethodAnnotationType)
+ && mustHaveTestAnnotationRemoved(m)) {
+ removeTestMethodAnnotationFrom(m);
+ }
+ }
+ }
+
+ @Override
+ public CtClass transform(final CtClass clazz) throws Exception {
+ if (clazz.isFrozen()) {
+ clazz.defrost();
+ }
+
+ if (isTestClass(clazz)) {
+ removeTestAnnotationsForTestMethodsThatRunOnOtherClassLoader(clazz);
+ addLifeCycleNotifications(clazz);
+ makeDeferConstructorNonPublic(clazz);
+ restoreOriginalConstructorsAccesses(clazz);
+
+ } else if (isNestedWithinTestClass(clazz)) {
+ makeDeferConstructorNonPublic(clazz);
+ restoreOriginalConstructorsAccesses(clazz);
+ }
+
+ return clazz;
+ }
+
+ private void addLifeCycleNotifications(CtClass clazz) {
+ try {
+ addClassInitializerNotification(clazz);
+ addConstructorNotification(clazz);
+ } catch (CannotCompileException ex) {
+ throw new Error("Powermock error: " + ex.getMessage(), ex);
+ }
+ }
+
+ private void addClassInitializerNotification(CtClass clazz)
+ throws CannotCompileException {
+ if (null == clazz.getClassInitializer()) {
+ clazz.makeClassInitializer();
+ }
+ clazz.getClassInitializer().insertBefore(
+ GlobalNotificationBuildSupport.class.getName()
+ + ".testClassInitiated(" + clazz.getName() + ".class);");
+ }
+
+ private static boolean hasSuperClass(CtClass clazz) {
+ try {
+ CtClass superClazz = clazz.getSuperclass();
+ /*
+ * Being extra careful here - and backup in case the
+ * work-in-progress clazz doesn't cause NotFoundException ...
+ */
+ return null != superClazz
+ && false == "java.lang.Object".equals(superClazz.getName());
+ } catch (NotFoundException noWasSuperClassFound) {
+ return false;
+ }
+ }
+
+ private void addConstructorNotification(final CtClass clazz)
+ throws CannotCompileException {
+ final String notificationCode =
+ GlobalNotificationBuildSupport.class.getName()
+ + ".testInstanceCreated(this);";
+ final boolean asFinally = false == hasSuperClass(clazz);
+ for (final CtConstructor constr : clazz.getDeclaredConstructors()) {
+ constr.insertAfter(
+ notificationCode,
+ asFinally/* unless there is a super-class, because of this
+ * problem: https://community.jboss.org/thread/94194*/);
+ }
+ }
+
+ private void restoreOriginalConstructorsAccesses(CtClass clazz) throws Exception {
+ Class<?> originalClass = testClass.getName().equals(clazz.getName())
+ ? testClass
+ : Class.forName(clazz.getName(), true, testClass.getClassLoader());
+ for (final CtConstructor ctConstr : clazz.getConstructors()) {
+ int ctModifiers = ctConstr.getModifiers();
+ if (false == Modifier.isPublic(ctModifiers)) {
+ /* Probably a defer-constructor */
+ continue;
+ }
+ int desiredAccessModifiers = originalClass.getDeclaredConstructor(
+ asOriginalClassParams(ctConstr.getParameterTypes())).getModifiers();
+
+ if (Modifier.isPrivate(desiredAccessModifiers)) {
+ ctConstr.setModifiers(Modifier.setPrivate(ctModifiers));
+ } else if (Modifier.isProtected(desiredAccessModifiers)) {
+ ctConstr.setModifiers(Modifier.setProtected(ctModifiers));
+ } else if (false == Modifier.isPublic(desiredAccessModifiers)) {
+ ctConstr.setModifiers(Modifier.setPackage(ctModifiers));
+ } else {
+ /* ctConstr remains public */
+ }
+ }
+ }
+
+ private void makeDeferConstructorNonPublic(final CtClass clazz) {
+ for (final CtConstructor constr : clazz.getConstructors()) {
+ try {
+ for (CtClass paramType : constr.getParameterTypes()) {
+ if (IndicateReloadClass.class.getName()
+ .equals(paramType.getName())) {
+ /* Found defer constructor ... */
+ final int modifiers = constr.getModifiers();
+ if (Modifier.isPublic(modifiers)) {
+ constr.setModifiers(Modifier.setProtected(modifiers));
+ }
+ break;
+ }
+ }
+ } catch (NotFoundException thereAreNoParameters) {
+ /* ... but to get an exception here seems odd. */
+ }
+ }
+ }
+
+ private static String signatureOf(Method m) {
+ Class<?>[] paramTypes = m.getParameterTypes();
+ String[] paramTypeNames = new String[paramTypes.length];
+ for (int i = 0; i < paramTypeNames.length; ++i) {
+ paramTypeNames[i] = paramTypes[i].getSimpleName();
+ }
+ return createSignature(
+ m.getDeclaringClass().getSimpleName(),
+ m.getReturnType().getSimpleName(),
+ m.getName(), paramTypeNames);
+ }
+
+ private static String signatureOf(CtMethod m) throws NotFoundException {
+ CtClass[] paramTypes = m.getParameterTypes();
+ String[] paramTypeNames = new String[paramTypes.length];
+ for (int i = 0; i < paramTypeNames.length; ++i) {
+ paramTypeNames[i] = paramTypes[i].getSimpleName();
+ }
+ return createSignature(
+ m.getDeclaringClass().getSimpleName(),
+ m.getReturnType().getSimpleName(),
+ m.getName(), paramTypeNames);
+ }
+
+ private static String createSignature(
+ String testClass, String returnType, String methodName, String[] paramTypes) {
+ StringBuilder builder = new StringBuilder(testClass)
+ .append('\n').append(returnType)
+ .append('\n').append(methodName);
+ for (String param : paramTypes) {
+ builder.append('\n').append(param);
+ }
+ return builder.toString();
+ }
+}
diff --git a/core/src/main/java/org/powermock/mockpolicies/MockPolicyClassLoadingSettings.java b/core/src/main/java/org/powermock/mockpolicies/MockPolicyClassLoadingSettings.java
new file mode 100644
index 0000000..9b1209b
--- /dev/null
+++ b/core/src/main/java/org/powermock/mockpolicies/MockPolicyClassLoadingSettings.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.mockpolicies;
+
+/**
+ * Contains class-loading related settings. PowerMock uses the information
+ * stored in this object to configure it's mock classloader to allow for
+ * testability.
+ * <p>
+ * Since mock policies can be chained subsequent policies can override behavior
+ * of a previous policy. To avoid accidental overrides it's recommended
+ * <i>add</i> behavior instead of <i>setting</i> behavior since the latter
+ * overrides all previous configurations.
+ */
+public interface MockPolicyClassLoadingSettings {
+
+ /**
+ * Set which static initializers to suppress. Note that this overrides all
+ * previous configurations.
+ */
+ void setStaticInitializersToSuppress(String[] staticInitializersToSuppress);
+
+ /**
+ * Add static initializers to suppress.
+ */
+ void addStaticInitializersToSuppress(String firstStaticInitializerToSuppress, String... additionalStaticInitializersToSuppress);
+
+ /**
+ * Add static initializers to suppress.
+ */
+ void addStaticInitializersToSuppress(String[] staticInitializersToSuppress);
+
+ /**
+ * Set which types that should be loaded (and possibly modified) by the mock
+ * classloader. Note that this overrides all previous configurations.
+ */
+ void setFullyQualifiedNamesOfClassesToLoadByMockClassloader(String[] classes);
+
+ /**
+ * Add types that should be loaded (and possibly modified) by the mock
+ * classloader.
+ */
+ void addFullyQualifiedNamesOfClassesToLoadByMockClassloader(String firstClass, String... additionalClasses);
+
+ /**
+ * Add types that should be loaded (and possibly modified) by the mock
+ * classloader.
+ */
+ void addFullyQualifiedNamesOfClassesToLoadByMockClassloader(String[] classes);
+
+ /**
+ * @return The fully-qualified names to the classes whose static
+ * initializers that should be suppressed.
+ */
+ String[] getStaticInitializersToSuppress();
+
+ /**
+ * @return The fully-qualified names to all types that should be loaded by
+ * the mock classloader.
+ */
+ String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader();
+}
diff --git a/core/src/main/java/org/powermock/mockpolicies/MockPolicyInterceptionSettings.java b/core/src/main/java/org/powermock/mockpolicies/MockPolicyInterceptionSettings.java
new file mode 100644
index 0000000..f214025
--- /dev/null
+++ b/core/src/main/java/org/powermock/mockpolicies/MockPolicyInterceptionSettings.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.mockpolicies;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.Map;
+
+/**
+ * Contains interception related settings. PowerMock uses the information stored
+ * in this object to intercept method calls and field calls etc and specify a
+ * return value or suppression.
+ * <p>
+ * Since mock policies can be chained subsequent policies can override behavior
+ * of a previous policy. To avoid accidental overrides it's recommended
+ * <i>add</i> behavior instead of <i>setting</i> behavior since the latter
+ * overrides all previous configurations.
+ */
+public interface MockPolicyInterceptionSettings {
+ /**
+ * Set which methods to suppress. Note that this overrides all previous
+ * configurations.
+ */
+ void setMethodsToSuppress(Method[] methods);
+
+ /**
+ * Add methods to suppress upon invocation.
+ */
+ void addMethodsToSuppress(Method methodToSuppress, Method... additionalMethodsToSuppress);
+
+ /**
+ * Add methods to suppress upon invocation.
+ */
+ void addMethodsToSuppress(Method[] methods);
+
+ /**
+ * Set the substitute return values. The substitute return values is a
+ * key-value map where each key is a method that should be intercepted and
+ * each value is the new return value for that method when it's intercepted.
+ * <p>
+ * Note that this overrides all previous configurations.
+ */
+ void setMethodsToStub(Map<Method, Object> substituteReturnValues);
+
+ /**
+ * Add a method that should be intercepted and return another value (
+ * <code>returnObject</code>) (i.e. the method is stubbed).
+ */
+ void stubMethod(Method method, Object returnObject);
+
+ /**
+ * Proxy a method with the given invocation handler. Each call to the method
+ * will be routed to the invocationHandler instead.
+ */
+ void proxyMethod(Method method, InvocationHandler invocationHandler);
+
+ /**
+ * Get all methods that should be proxied and the invocation handler for
+ * each method.
+ */
+ Map<Method, InvocationHandler> getProxiedMethods();
+
+ /**
+ * Set the methods to proxy. The proxies are a key-value map where each key
+ * is a method that should be intercepted and routed to the invocation
+ * handler instead.
+ * <p>
+ * Note that this overrides all previous configurations.
+ */
+ void setMethodsToProxy(Map<Method, InvocationHandler> proxies);
+
+ /**
+ * Set the substitute return values. The substitute return values is a
+ * key-value map where each key is a method that should be intercepted and
+ * each value is the new return value for that method when it's intercepted.
+ * <p>
+ * Note that this overrides all previous configurations.
+ *
+ * @deprecated Use {@link #stubMethod(Method, Object)} instead.
+ */
+ void setSubtituteReturnValues(Map<Method, Object> substituteReturnValues);
+
+ /**
+ * Add a method that should be intercepted and return another value (
+ * <code>returnObject</code>). The substitute return values is a key-value
+ * map where each key is a method that should be intercepted and each value
+ * is the new return value for that method when it's intercepted.
+ *
+ * @deprecated Use {@link #stubMethod(Method, Object)} instead.
+ */
+ void addSubtituteReturnValue(Method method, Object returnObject);
+
+ /**
+ * Set specific fields that should be suppressed upon invocation. Note that
+ * this overrides all previous configurations.
+ */
+ void setFieldsSuppress(Field[] fields);
+
+ /**
+ * Add specific fields that should be suppressed upon invocation.
+ */
+ void addFieldToSuppress(Field firstField, Field... additionalFields);
+
+ /**
+ * Add specific fields that should be suppressed upon invocation.
+ */
+ void addFieldToSuppress(Field[] fields);
+
+ /**
+ * Set which field types that should be suppressed. Note that this overrides
+ * all previous configurations.
+ */
+ void setFieldTypesToSuppress(String[] fieldTypes);
+
+ /**
+ * Add field types that should be suppressed.
+ */
+ void addFieldTypesToSuppress(String firstType, String... additionalFieldTypes);
+
+ /**
+ * Add field types that should be suppressed.
+ */
+ void addFieldTypesToSuppress(String[] fieldTypes);
+
+ /**
+ * @return Which methods that should be suppressed/stubbed (i.e. return a
+ * default value when invoked).
+ */
+ Method[] getMethodsToSuppress();
+
+ /**
+ * Get all substitute return values and also returns an unmodifiable map of
+ * all method-object pairs the were initialized.
+ */
+ Map<Method, Object> getStubbedMethods();
+
+ /**
+ * Get all substitute return values and also returns an unmodifiable map of
+ * all method-object pairs the were initialized.
+ *
+ * @deprecated Use {@link #getStubbedMethods()} instead.
+ */
+ Map<Method, Object> getSubstituteReturnValues();
+
+ /**
+ * @return Which fields should be suppressed (i.e. will be set to
+ * <code>null</code> or other default values).
+ */
+ Field[] getFieldsToSuppress();
+
+ /**
+ * @return The fully-qualified names to the fields that should be
+ * suppressed.
+ */
+ String[] getFieldTypesToSuppress();
+}
diff --git a/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyClassLoadingSettingsImpl.java b/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyClassLoadingSettingsImpl.java
new file mode 100644
index 0000000..7a17436
--- /dev/null
+++ b/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyClassLoadingSettingsImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.mockpolicies.impl;
+
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * The default implementation of the {@link MockPolicyClassLoadingSettings}
+ * interface.
+ */
+public class MockPolicyClassLoadingSettingsImpl implements MockPolicyClassLoadingSettings {
+ private Set<String> fullyQualifiedNamesOfClassesToLoadByMockClassloader;
+ private Set<String> staticInitializersToSuppress;
+
+ public MockPolicyClassLoadingSettingsImpl() {
+ fullyQualifiedNamesOfClassesToLoadByMockClassloader = new LinkedHashSet<String>();
+ staticInitializersToSuppress = new LinkedHashSet<String>();
+ }
+
+ @Override
+ public String[] getFullyQualifiedNamesOfClassesToLoadByMockClassloader() {
+ if (fullyQualifiedNamesOfClassesToLoadByMockClassloader == null) {
+ return new String[0];
+ }
+ return fullyQualifiedNamesOfClassesToLoadByMockClassloader.toArray(new String[fullyQualifiedNamesOfClassesToLoadByMockClassloader.size()]);
+ }
+
+ @Override
+ public String[] getStaticInitializersToSuppress() {
+ if (staticInitializersToSuppress == null) {
+ return new String[0];
+ }
+ return staticInitializersToSuppress.toArray(new String[staticInitializersToSuppress.size()]);
+ }
+
+ @Override
+ public void addFullyQualifiedNamesOfClassesToLoadByMockClassloader(String firstClass, String... additionalClasses) {
+ fullyQualifiedNamesOfClassesToLoadByMockClassloader.add(firstClass);
+ addFullyQualifiedNamesOfClassesToLoadByMockClassloader(additionalClasses);
+ }
+
+ @Override
+ public void addFullyQualifiedNamesOfClassesToLoadByMockClassloader(String[] classes) {
+ for (String clazz : classes) {
+ fullyQualifiedNamesOfClassesToLoadByMockClassloader.add(clazz);
+ }
+ }
+
+ @Override
+ public void addStaticInitializersToSuppress(String firstStaticInitializerToSuppress, String... additionalStaticInitializersToSuppress) {
+ staticInitializersToSuppress.add(firstStaticInitializerToSuppress);
+ addStaticInitializersToSuppress(additionalStaticInitializersToSuppress);
+ }
+
+ @Override
+ public void addStaticInitializersToSuppress(String[] staticInitializersToSuppress) {
+ for (String staticInitializerToSuppress : staticInitializersToSuppress) {
+ this.staticInitializersToSuppress.add(staticInitializerToSuppress);
+ }
+ }
+
+ @Override
+ public void setFullyQualifiedNamesOfClassesToLoadByMockClassloader(String[] classes) {
+ fullyQualifiedNamesOfClassesToLoadByMockClassloader.clear();
+ addFullyQualifiedNamesOfClassesToLoadByMockClassloader(classes);
+ }
+
+ @Override
+ public void setStaticInitializersToSuppress(String[] staticInitializersToSuppress) {
+ this.staticInitializersToSuppress.clear();
+ addStaticInitializersToSuppress(staticInitializersToSuppress);
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyInterceptionSettingsImpl.java b/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyInterceptionSettingsImpl.java
new file mode 100644
index 0000000..ba76caf
--- /dev/null
+++ b/core/src/main/java/org/powermock/mockpolicies/impl/MockPolicyInterceptionSettingsImpl.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.mockpolicies.impl;
+
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+import java.util.*;
+
+public class MockPolicyInterceptionSettingsImpl implements MockPolicyInterceptionSettings {
+ private Set<Field> fieldsToSuppress;
+ private Set<Method> methodsToSuppress;
+ private Map<Method, Object> substituteReturnValues;
+ private Set<String> fieldsTypesToSuppress;
+ private Map<Method, InvocationHandler> proxies;
+
+ public MockPolicyInterceptionSettingsImpl() {
+ fieldsToSuppress = new LinkedHashSet<Field>();
+ methodsToSuppress = new LinkedHashSet<Method>();
+ substituteReturnValues = new HashMap<Method, Object>();
+ proxies = new HashMap<Method, InvocationHandler>();
+ fieldsTypesToSuppress = new LinkedHashSet<String>();
+ }
+
+ @Override
+ public void addFieldTypesToSuppress(String firstType, String... additionalFieldTypes) {
+ fieldsTypesToSuppress.add(firstType);
+ addFieldTypesToSuppress(additionalFieldTypes);
+ }
+
+ @Override
+ public void addFieldTypesToSuppress(String[] fieldTypes) {
+ for (String fieldType : fieldTypes) {
+ fieldsTypesToSuppress.add(fieldType);
+ }
+ }
+
+ @Override
+ public void setFieldTypesToSuppress(String[] fieldTypes) {
+ fieldsTypesToSuppress.clear();
+ addFieldTypesToSuppress(fieldTypes);
+ }
+
+ @Override
+ public Field[] getFieldsToSuppress() {
+ return fieldsToSuppress.toArray(new Field[fieldsToSuppress.size()]);
+ }
+
+ @Override
+ public Method[] getMethodsToSuppress() {
+ return methodsToSuppress.toArray(new Method[methodsToSuppress.size()]);
+ }
+
+ @Override
+ public Map<Method, Object> getStubbedMethods() {
+ return Collections.unmodifiableMap(substituteReturnValues);
+ }
+
+ @Override
+ public void addFieldToSuppress(Field firstField, Field... fields) {
+ fieldsToSuppress.add(firstField);
+ addFieldToSuppress(fields);
+ }
+
+ @Override
+ public void addFieldToSuppress(Field[] fields) {
+ for (Field field : fields) {
+ fieldsToSuppress.add(field);
+ }
+ }
+
+ @Override
+ public void addMethodsToSuppress(Method methodToSuppress, Method... additionalMethodsToSuppress) {
+ methodsToSuppress.add(methodToSuppress);
+ addMethodsToSuppress(additionalMethodsToSuppress);
+ }
+
+ @Override
+ public void addMethodsToSuppress(Method[] methods) {
+ for (Method method : methods) {
+ methodsToSuppress.add(method);
+ }
+ }
+
+ @Override
+ public void stubMethod(Method method, Object returnObject) {
+ substituteReturnValues.put(method, returnObject);
+ }
+
+ @Override
+ public void setFieldsSuppress(Field[] fields) {
+ fieldsToSuppress.clear();
+ addFieldToSuppress(fields);
+ }
+
+ @Override
+ public void setMethodsToSuppress(Method[] methods) {
+ methodsToSuppress.clear();
+ addMethodsToSuppress(methods);
+ }
+
+ @Override
+ public void setMethodsToStub(Map<Method, Object> substituteReturnValues) {
+ this.substituteReturnValues = substituteReturnValues;
+ }
+
+ @Override
+ public String[] getFieldTypesToSuppress() {
+ return fieldsTypesToSuppress.toArray(new String[fieldsTypesToSuppress.size()]);
+ }
+
+ @Override
+ public void addSubtituteReturnValue(Method method, Object returnObject) {
+ substituteReturnValues.put(method, returnObject);
+ }
+
+ @Override
+ public void setSubtituteReturnValues(Map<Method, Object> substituteReturnValues) {
+ this.substituteReturnValues = substituteReturnValues;
+ }
+
+ @Override
+ public Map<Method, Object> getSubstituteReturnValues() {
+ return getStubbedMethods();
+ }
+
+ @Override
+ public Map<Method, InvocationHandler> getProxiedMethods() {
+ return proxies;
+ }
+
+ @Override
+ public void proxyMethod(Method method, InvocationHandler invocationHandler) {
+ proxies.put(method, invocationHandler);
+ }
+
+ @Override
+ public void setMethodsToProxy(Map<Method, InvocationHandler> proxies) {
+ this.proxies = proxies;
+ }
+}
diff --git a/core/src/main/java/org/powermock/mockpolicies/support/LogPolicySupport.java b/core/src/main/java/org/powermock/mockpolicies/support/LogPolicySupport.java
new file mode 100644
index 0000000..91675f8
--- /dev/null
+++ b/core/src/main/java/org/powermock/mockpolicies/support/LogPolicySupport.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.mockpolicies.support;
+
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+
+/**
+ * A support class for mock policies dealing with logging frameworks.
+ */
+public class LogPolicySupport {
+ /**
+ * Get the methods that should be mocked.
+ *
+ * @param fullyQualifiedClassName
+ * The fully-qualified name to the class that contains the
+ * method.
+ * @param methodName
+ * The name of the method that should be mocked.
+ * @param logFramework
+ * The log framework that should be printed if the class
+ * <code>fullyQualifiedClassName</code> cannot be found.
+ * @return The {@link Method[]}'s that should be mocked.
+ */
+ public Method[] getLoggerMethods(String fullyQualifiedClassName, String methodName, String logFramework) {
+ try {
+ return Whitebox.getMethods(getType(fullyQualifiedClassName, logFramework), methodName);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Get the class type representing the fully-qualified name.
+ *
+ * @param name
+ * The fully-qualified name of a class to get.
+ * @param logFramework
+ * The log framework that should be printed if the class cannot
+ * be found.
+ * @return The class representing the fully-qualified name.
+ * @throws Exception
+ * If something unexpected goes wrong, for example if the class
+ * cannot be found.
+ */
+ public Class<?> getType(String name, String logFramework) throws Exception {
+ Class<?> loggerType = null;
+ try {
+ loggerType = Class.forName(name);
+ } catch (ClassNotFoundException e) {
+ final String message = String.format("Cannot find %s in the classpath which the %s policy requires.", logFramework, getClass()
+ .getSimpleName());
+ throw new RuntimeException(message, e);
+ }
+ return loggerType;
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/ArrayMerger.java b/core/src/main/java/org/powermock/tests/utils/ArrayMerger.java
new file mode 100644
index 0000000..b9be3dd
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/ArrayMerger.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+/**
+ * An array merger concatenates several arrays to one.
+ */
+public interface ArrayMerger {
+
+ /**
+ * Merge arrays of a specific type.
+ */
+ <T> T[] mergeArrays(Class<T> type, T[]... arraysToMerge);
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/IgnorePackagesExtractor.java b/core/src/main/java/org/powermock/tests/utils/IgnorePackagesExtractor.java
new file mode 100644
index 0000000..978e154
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/IgnorePackagesExtractor.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import java.lang.reflect.AnnotatedElement;
+
+public interface IgnorePackagesExtractor {
+ /**
+ * @return Returns a string-array of all package names if annotation was
+ * found.
+ */
+ String[] getPackagesToIgnore(AnnotatedElement element);
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/Keys.java b/core/src/main/java/org/powermock/tests/utils/Keys.java
new file mode 100644
index 0000000..d8b242a
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/Keys.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+/**
+ * Holds various keys that may be put into the MockRepository to store state.
+ */
+public class Keys {
+
+ /**
+ * Key that can be used to set or get the current test instance in the mock
+ * repository.
+ */
+ public static final String CURRENT_TEST_INSTANCE = "powermock.test.instance";
+
+ /**
+ * Key that can be used to set or get the current test method in the mock
+ * repository.
+ */
+ public static final String CURRENT_TEST_METHOD = "powermock.test.method";
+
+ /**
+ * Key that can be used to set or get the current test method arguments in
+ * the mock repository.
+ */
+ public static final String CURRENT_TEST_METHOD_ARGUMENTS = "powermock.test.arguments";
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/MockPolicyInitializer.java b/core/src/main/java/org/powermock/tests/utils/MockPolicyInitializer.java
new file mode 100644
index 0000000..98b7c60
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/MockPolicyInitializer.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import org.powermock.core.classloader.MockClassLoader;
+
+/**
+ * A Mock Policy initializer takes care of initializing the behavior defined by
+ * the mock policies.
+ */
+public interface MockPolicyInitializer {
+
+ /**
+ * Initializes the mock policies for a given class loader. Note that this
+ * method must <b><i>not</i></b> be called from the class loader (
+ * <code>classLoader</code>) that you pass in to this method.
+ * <p>
+ * Note that if the class-loader is not an instance of
+ * {@link MockClassLoader} this method will return silently.
+ */
+ void initialize(ClassLoader classLoader);
+
+ /**
+ * @return <code>true</code> if a client needs to perform initialization for
+ * this {@link MockPolicyInitializer}, <code>false</code> otherwise.
+ */
+ boolean needsInitialization();
+
+ /**
+ * @return <code>true</code> if the class with the fully-qualified name of
+ * <code>fullyQualifiedClassName</code> was prepared for testing by
+ * this mock policy initializer.
+ */
+ boolean isPrepared(String fullyQualifiedClassName);
+
+ /**
+ * Re executes the {@link MockPolicy#} of all the policies for a given class
+ * loader. This method must be called after a call to
+ * {@link MockPolicyInitializer#initialize(ClassLoader)} on the same class
+ * loader.
+ * <p>
+ * Note that if the class-loader is not an instance of
+ * {@link MockClassLoader} this method will return silently.
+ */
+ void refreshPolicies(ClassLoader classLoader);
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/PowerMockTestNotifier.java b/core/src/main/java/org/powermock/tests/utils/PowerMockTestNotifier.java
new file mode 100644
index 0000000..c7d67cc
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/PowerMockTestNotifier.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+
+import java.lang.reflect.Method;
+
+/**
+ * Implementors of this interface that must provide the ability to notify
+ * PowerMock test listeners with the events as specified by the methods declared
+ * in this interface.
+ */
+public interface PowerMockTestNotifier {
+
+ /**
+ * Notifies all listeners with the "before test method started" event.
+ */
+ void notifyBeforeTestMethod(final Object testInstance, final Method testMethod, final Object[] arguments);
+
+ /**
+ * Notifies all listeners with the "after test method ended" event.
+ */
+ void notifyAfterTestMethod(Object testInstance, Method method, Object[] arguments, TestMethodResult testResult);
+
+ /**
+ * Notifies all listeners with the "after test method ended" event. Uses
+ * some state-store to get the needed state. For this method to work
+ * {@link #notifyBeforeTestMethod(Object, Method, Object[])} must have been
+ * called before this method. Otherwise revert to using the
+ * {@link #notifyAfterTestMethod(Object, Method, Object[], TestMethodResult)}
+ * method.
+ *
+ * @param successful
+ * <code>true</code> if the test was successful,
+ * <code>false</code> otherwise.
+ */
+ void notifyAfterTestMethod(boolean successful);
+
+ /**
+ * Notifies all listeners with the "before test suite started" event.
+ */
+ void notifyBeforeTestSuiteStarted(final Class<?> testClass, final Method[] testMethods);
+
+ /**
+ * Notifies all listeners with the "after test suite ended" event.
+ */
+ void notifyAfterTestSuiteEnded(Class<?> testClass, Method[] methods, TestSuiteResult testResult);
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/RunnerTestSuiteChunker.java b/core/src/main/java/org/powermock/tests/utils/RunnerTestSuiteChunker.java
new file mode 100644
index 0000000..6b65d6a
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/RunnerTestSuiteChunker.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import java.util.List;
+
+/**
+ * An interface that should be implemented by classes that performs test suite
+ * chunking. Test suite chunking may be performed because certain classes may
+ * need to be byte-code manipulated in tests without impacting on other tests.
+ *
+ * @author Johan Haleby
+ */
+public interface RunnerTestSuiteChunker extends TestSuiteChunker {
+
+ /**
+ * Create the test delegators needed for a whole class.
+ */
+ void createTestDelegators(Class<?> testClass, List<TestChunk> chunks) throws Exception;
+
+
+ /**
+ * Get the number of total tests defined in the suite (the sum of all tests
+ * defined in all chunks for this suite).
+ *
+ * @return The number of tests in this suite.
+ */
+ int getTestCount();
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/TestChunk.java b/core/src/main/java/org/powermock/tests/utils/TestChunk.java
new file mode 100644
index 0000000..f74f29b
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/TestChunk.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * A test chunk consists of a list of methods that should be executed by a
+ * particular classloader.
+ * */
+public interface TestChunk {
+
+ ClassLoader getClassLoader();
+
+ List<Method> getTestMethodsToBeExecutedByThisClassloader();
+
+ boolean isMethodToBeExecutedByThisClassloader(Method method);
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/powermock/tests/utils/TestClassesExtractor.java b/core/src/main/java/org/powermock/tests/utils/TestClassesExtractor.java
new file mode 100644
index 0000000..7fd98f0
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/TestClassesExtractor.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils;
+
+import java.lang.reflect.AnnotatedElement;
+
+public interface TestClassesExtractor {
+ /**
+ * @return Returns <code>null</code> if the element was not annotated, an
+ * empty String[] if it is annotated but contains no classes, or a
+ * string-array of all class names if interest.
+ */
+ String[] getTestClasses(AnnotatedElement element);
+
+ boolean isPrepared(AnnotatedElement element, String fullyQualifiedClassName);
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/TestSuiteChunker.java b/core/src/main/java/org/powermock/tests/utils/TestSuiteChunker.java
new file mode 100644
index 0000000..57a0184
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/TestSuiteChunker.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.tests.utils;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ *
+ */
+public interface TestSuiteChunker {
+
+
+ /**
+ * Get the number of chunks defined in this suite.
+ *
+ * @return The number of chunks defined in the correct suite.
+ */
+ int getChunkSize();
+
+ /**
+ * Get all chunk entries.
+ *
+ * @return An set of entries that contains a list of methods contained in
+ * the chunk and the class loader that loaded these methods.
+ */
+ List<TestChunk> getTestChunks();
+
+ /**
+ * Get all chunk entries for a specific class.
+ *
+ * @param testClass The class whose chunk entries to get.
+ * @return An set of entries that contains a list of methods contained in
+ * the chunk for the specific test class and the class loader that
+ * loaded these methods.
+ */
+ List<TestChunk> getTestChunksEntries(Class<?> testClass);
+
+ /**
+ * Get TestChunk for the given method.
+ *
+ * @param method - method for which test chunk should be found.
+ * @return TestChunk for this method.
+ */
+ TestChunk getTestChunk(Method method);
+
+ /**
+ * Should reflect whether or not this method is eligible for testing.
+ *
+ * @param testClass The class that defines the method.
+ * @param potentialTestMethod The method to inspect whether it should be executed in the
+ * test suite or not.
+ * @return <code>true</code> if the method is a test method and should be
+ * executed, <code>false</code> otherwise.
+ */
+ boolean shouldExecuteTestForMethod(Class<?> testClass, Method potentialTestMethod);
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/AbstractCommonTestSuiteChunkerImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/AbstractCommonTestSuiteChunkerImpl.java
new file mode 100644
index 0000000..39e04bf
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/AbstractCommonTestSuiteChunkerImpl.java
@@ -0,0 +1,268 @@
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.PrepareEverythingForTest;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.impl.TestClassTransformer;
+import org.powermock.reflect.proxyframework.ClassLoaderRegisterProxyFramework;
+import org.powermock.tests.utils.ArrayMerger;
+import org.powermock.tests.utils.IgnorePackagesExtractor;
+import org.powermock.tests.utils.TestChunk;
+import org.powermock.tests.utils.TestClassesExtractor;
+import org.powermock.tests.utils.TestSuiteChunker;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ */
+public abstract class AbstractCommonTestSuiteChunkerImpl implements TestSuiteChunker {
+
+ protected static final int DEFAULT_TEST_LISTENERS_SIZE = 1;
+
+ protected static final int NOT_INITIALIZED = -1;
+
+ protected static final int INTERNAL_INDEX_NOT_FOUND = NOT_INITIALIZED;
+
+ /*
+ * Maps between a specific class and a map of test methods loaded by a
+ * specific mock class loader.
+ */
+ private final List<TestCaseEntry> internalSuites = new LinkedList<TestCaseEntry>();
+ private final TestClassesExtractor prepareForTestExtractor = new PrepareForTestExtractorImpl();
+ private final TestClassesExtractor suppressionExtractor = new StaticConstructorSuppressExtractorImpl();
+ /*
+ * Maps the list of test indexes that is assigned to a specific test suite
+ * index.
+ */
+ protected final LinkedHashMap<Integer, List<Integer>> testAtDelegateMapper = new LinkedHashMap<Integer, List<Integer>>();
+ protected final Class<?>[] testClasses;
+ private final IgnorePackagesExtractor ignorePackagesExtractor = new PowerMockIgnorePackagesExtractorImpl();
+ private final ArrayMerger arrayMerger = new ArrayMergerImpl();
+ private int currentTestIndex = NOT_INITIALIZED;
+
+
+ protected AbstractCommonTestSuiteChunkerImpl(Class<?> testClass) throws Exception {
+ this(new Class[]{testClass});
+ }
+
+ protected AbstractCommonTestSuiteChunkerImpl(Class<?>... testClasses) throws Exception {
+ this.testClasses = testClasses;
+ for (Class<?> clazz : testClasses) {
+ chunkClass(clazz);
+ }
+ }
+
+ @Override
+ public int getChunkSize() {
+ return getTestChunks().size();
+ }
+
+ public List<TestChunk> getTestChunks() {
+ List<TestChunk> allChunks = new LinkedList<TestChunk>();
+ for (TestCaseEntry entry : internalSuites) {
+ for (TestChunk chunk : entry.getTestChunks()) {
+ allChunks.add(chunk);
+ }
+ }
+ return allChunks;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public List<TestChunk> getTestChunksEntries(Class<?> testClass) {
+ for (TestCaseEntry entry : internalSuites) {
+ if (entry.getTestClass().equals(testClass)) {
+ return entry.getTestChunks();
+ }
+ }
+ return null;
+ }
+
+ public TestChunk getTestChunk(Method method) {
+ for (TestChunk testChunk : getTestChunks()) {
+ if (testChunk.isMethodToBeExecutedByThisClassloader(method)) {
+ return testChunk;
+ }
+ }
+ return null;
+ }
+
+ protected void registerProxyframework(ClassLoader classLoader) {
+ ClassLoaderRegisterProxyFramework.registerProxyframework(classLoader);
+ }
+
+ protected void chunkClass(final Class<?> testClass) throws Exception {
+
+ List<Method> testMethodsForOtherClassLoaders = new ArrayList<Method>();
+
+ MockTransformer[] extraMockTransformers = createDefaultExtraMockTransformers(testClass, testMethodsForOtherClassLoaders);
+
+ final String[] ignorePackages = ignorePackagesExtractor.getPackagesToIgnore(testClass);
+
+ final ClassLoader defaultMockLoader = createDefaultMockLoader(testClass, extraMockTransformers, ignorePackages);
+
+ registerProxyframework(defaultMockLoader);
+
+ List<Method> currentClassloaderMethods = new LinkedList<Method>();
+ // Put the first suite in the map of internal suites.
+ TestChunk defaultTestChunk = new TestChunkImpl(defaultMockLoader, currentClassloaderMethods);
+ List<TestChunk> testChunks = new LinkedList<TestChunk>();
+ testChunks.add(defaultTestChunk);
+ internalSuites.add(new TestCaseEntry(testClass, testChunks));
+ initEntries(internalSuites);
+
+ if (!currentClassloaderMethods.isEmpty()) {
+ List<TestChunk> allTestChunks = internalSuites.get(0).getTestChunks();
+ for (TestChunk chunk : allTestChunks.subList(1, allTestChunks.size())) {
+ for (Method m : chunk.getTestMethodsToBeExecutedByThisClassloader()) {
+ testMethodsForOtherClassLoaders.add(m);
+ }
+ }
+ } else if (2 <= internalSuites.size()
+ || 1 == internalSuites.size()
+ && 2 <= internalSuites.get(0).getTestChunks().size()) {
+ /*
+ * If we don't have any test that should be executed by the default
+ * class loader remove it to avoid duplicate test print outs.
+ */
+ internalSuites.get(0).getTestChunks().remove(0);
+ }
+ //else{ /*Delegation-runner maybe doesn't use test-method annotations!*/ }
+ }
+
+ private ClassLoader createDefaultMockLoader(Class<?> testClass, MockTransformer[] extraMockTransformers, String[] ignorePackages) {
+ final ClassLoader defaultMockLoader;
+ if (testClass.isAnnotationPresent(PrepareEverythingForTest.class)) {
+ defaultMockLoader = createNewClassloader(testClass, new String[]{MockClassLoader.MODIFY_ALL_CLASSES},
+ ignorePackages, extraMockTransformers);
+ } else {
+ final String[] prepareForTestClasses = prepareForTestExtractor.getTestClasses(testClass);
+ final String[] suppressStaticClasses = suppressionExtractor.getTestClasses(testClass);
+ defaultMockLoader = createNewClassloader(testClass, arrayMerger.mergeArrays(String.class, prepareForTestClasses, suppressStaticClasses),
+ ignorePackages, extraMockTransformers);
+ }
+ return defaultMockLoader;
+ }
+
+ private ClassLoader createNewClassloader(Class<?> testClass, String[] classesToLoadByMockClassloader,
+ final String[] packagesToIgnore, MockTransformer... extraMockTransformers) {
+ final MockClassLoaderFactory classLoaderFactory = getMockClassLoaderFactory(testClass, classesToLoadByMockClassloader, packagesToIgnore, extraMockTransformers);
+ return classLoaderFactory.create();
+ }
+
+ protected MockClassLoaderFactory getMockClassLoaderFactory(Class<?> testClass, String[] preliminaryClassesToLoadByMockClassloader, String[] packagesToIgnore, MockTransformer[] extraMockTransformers) {
+ return new MockClassLoaderFactory(testClass, preliminaryClassesToLoadByMockClassloader, packagesToIgnore, extraMockTransformers);
+ }
+
+ private MockTransformer[] createDefaultExtraMockTransformers(Class<?> testClass, List<Method> testMethodsThatRunOnOtherClassLoaders) {
+ if (null == testMethodAnnotation()) {
+ return new MockTransformer[0];
+ } else {
+ return new MockTransformer[]{
+ TestClassTransformer
+ .forTestClass(testClass)
+ .removesTestMethodAnnotation(testMethodAnnotation())
+ .fromMethods(testMethodsThatRunOnOtherClassLoaders)
+ };
+ }
+ }
+
+ protected Class<? extends Annotation> testMethodAnnotation() {
+ return null;
+ }
+
+ private void initEntries(List<TestCaseEntry> entries) {
+ for (TestCaseEntry testCaseEntry : entries) {
+ final Class<?> testClass = testCaseEntry.getTestClass();
+ findMethods(testCaseEntry, testClass);
+ }
+ }
+
+ private void findMethods(TestCaseEntry testCaseEntry, Class<?> testClass) {
+ Method[] allMethods = testClass.getMethods();
+ for (Method method : allMethods) {
+ putMethodToChunk(testCaseEntry, testClass, method);
+ }
+ testClass = testClass.getSuperclass();
+ if (!Object.class.equals(testClass)) {
+ findMethods(testCaseEntry, testClass);
+ }
+ }
+
+ private void putMethodToChunk(TestCaseEntry testCaseEntry, Class<?> testClass, Method method) {
+ if (shouldExecuteTestForMethod(testClass, method)) {
+ currentTestIndex++;
+ if (hasChunkAnnotation(method)) {
+ LinkedList<Method> methodsInThisChunk = new LinkedList<Method>();
+ methodsInThisChunk.add(method);
+ final String[] staticSuppressionClasses = getStaticSuppressionClasses(testClass, method);
+ TestClassTransformer[] extraTransformers = null == testMethodAnnotation()
+ ? new TestClassTransformer[0]
+ : new TestClassTransformer[]{
+ TestClassTransformer.forTestClass(testClass)
+ .removesTestMethodAnnotation(testMethodAnnotation())
+ .fromAllMethodsExcept(method)
+ };
+
+ final ClassLoader mockClassloader;
+ if (method.isAnnotationPresent(PrepareEverythingForTest.class)) {
+ mockClassloader = createNewClassloader(testClass, new String[]{MockClassLoader.MODIFY_ALL_CLASSES},
+ ignorePackagesExtractor.getPackagesToIgnore(testClass), extraTransformers);
+ } else {
+ mockClassloader = createNewClassloader(testClass, arrayMerger.mergeArrays(String.class, prepareForTestExtractor.getTestClasses(method),
+ staticSuppressionClasses), ignorePackagesExtractor.getPackagesToIgnore(testClass), extraTransformers);
+ }
+ TestChunkImpl chunk = new TestChunkImpl(mockClassloader, methodsInThisChunk);
+ testCaseEntry.getTestChunks().add(chunk);
+ updatedIndexes();
+ } else {
+ testCaseEntry.getTestChunks().get(0).getTestMethodsToBeExecutedByThisClassloader().add(method);
+ // currentClassloaderMethods.add(method);
+ final int currentDelegateIndex = internalSuites.size() - 1;
+ /*
+ * Add this test index to the main junit runner
+ * delegator.
+ */
+ List<Integer> testList = testAtDelegateMapper.get(currentDelegateIndex);
+ if (testList == null) {
+ testList = new LinkedList<Integer>();
+ testAtDelegateMapper.put(currentDelegateIndex, testList);
+ }
+
+ testList.add(currentTestIndex);
+ }
+ }
+ }
+
+ private boolean hasChunkAnnotation(Method method) {
+ return method.isAnnotationPresent(PrepareForTest.class) || method.isAnnotationPresent(SuppressStaticInitializationFor.class)
+ || method.isAnnotationPresent(PrepareOnlyThisForTest.class) || method.isAnnotationPresent(PrepareEverythingForTest.class);
+ }
+
+ private String[] getStaticSuppressionClasses(Class<?> testClass, Method method) {
+ final String[] testClasses;
+ if (method.isAnnotationPresent(SuppressStaticInitializationFor.class)) {
+ testClasses = suppressionExtractor.getTestClasses(method);
+ } else {
+ testClasses = suppressionExtractor.getTestClasses(testClass);
+ }
+ return testClasses;
+ }
+
+ private void updatedIndexes() {
+ final List<Integer> testIndexesForThisClassloader = new LinkedList<Integer>();
+ testIndexesForThisClassloader.add(currentTestIndex);
+ testAtDelegateMapper.put(internalSuites.size(), testIndexesForThisClassloader);
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestClassExtractor.java b/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestClassExtractor.java
new file mode 100644
index 0000000..0cd56b4
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestClassExtractor.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.tests.utils.TestClassesExtractor;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Base class for all test class extractors.
+ */
+public abstract class AbstractTestClassExtractor implements TestClassesExtractor {
+
+ protected final boolean includeMethods;
+
+ protected AbstractTestClassExtractor(){
+ this(false);
+ }
+
+ protected AbstractTestClassExtractor(boolean includeMethods) {this.includeMethods = includeMethods;}
+
+ /**
+ * If <code>element</code> is a class this method traverses the hierarchy
+ * and extracts classes that should be prepared for test in all super
+ * classes.
+ */
+ @Override
+ public final String[] getTestClasses(AnnotatedElement element) {
+ final Set<String> classesToPrepareForTest = new HashSet<String>();
+ if (element instanceof Class<?>) {
+ extractClassesFromTestClass((Class<?>) element, classesToPrepareForTest);
+ } else {
+ extractClassesAndAddThemToList(element, classesToPrepareForTest);
+ }
+ return classesToPrepareForTest.toArray(new String[classesToPrepareForTest.size()]);
+ }
+
+ private void extractClassesFromTestClass(final Class<?> element, Set<String> classesToPrepareForTest) {
+ Class<?> classToInvestigate = element;
+ while (classToInvestigate != null && !classToInvestigate.equals(Object.class)) {
+ extractClassesAndAddThemToList(classToInvestigate, classesToPrepareForTest);
+ if (includeMethods) {
+ classesToPrepareForTest.addAll(lookOverMethods(classToInvestigate));
+ }
+ classToInvestigate = classToInvestigate.getSuperclass();
+ }
+ }
+
+ private Collection<String> lookOverMethods(Class<?> classToInvestigate) {
+ Set<String> classesToPrepareForTest = new HashSet<String>();
+ for (Method method : classToInvestigate.getMethods()) {
+ extractClassesAndAddThemToList(method, classesToPrepareForTest);
+ }
+ return classesToPrepareForTest;
+ }
+
+ private void extractClassesAndAddThemToList(AnnotatedElement elementToExtractClassFrom, final Set<String> classesToPrepareForTest) {
+ final String[] classesToModify = getClassesToModify(elementToExtractClassFrom);
+ if (classesToModify != null) {
+ Collections.addAll(classesToPrepareForTest, classesToModify);
+ }
+ }
+
+ /**
+ * Get the fully qualified names for classes that must should be modified
+ * for this <code>element</code>.
+ *
+ * @param element The element that may contain info regarding which classes that
+ * must be modified by PowerMock.
+ * @return An array of fully-qualified names to classes that must be
+ * modified by PowerMock for the specific <code>element</code>.
+ */
+ protected abstract String[] getClassesToModify(AnnotatedElement element);
+
+ @Override
+ public boolean isPrepared(AnnotatedElement element, String fullyQualifiedClassName) {
+ if (fullyQualifiedClassName == null) {
+ throw new IllegalArgumentException("fullyQualifiedClassName cannot be null.");
+ }
+ final String[] testClasses = getTestClasses(element);
+ for (String className : testClasses) {
+ if (className.equals(fullyQualifiedClassName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestSuiteChunkerImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestSuiteChunkerImpl.java
new file mode 100644
index 0000000..3e8bced
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/AbstractTestSuiteChunkerImpl.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.classloader.annotations.PowerMockListener;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.reporter.MockingFrameworkReporterFactory;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.RunnerTestSuiteChunker;
+import org.powermock.tests.utils.TestChunk;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Abstract base class for test suite chunking, i.e. a suite is chunked into
+ * several smaller pieces which are ran with different classloaders. A chunk is
+ * defined by the {@link PrepareForTest} annotation and whichever test-method
+ * annotation the actual implementation-class specifies by overriding the
+ * method {@link #testMethodAnnotation()}. This to make sure that you
+ * can byte-code manipulate classes in tests without impacting on other tests.
+ *
+ */
+public abstract class AbstractTestSuiteChunkerImpl<T> extends AbstractCommonTestSuiteChunkerImpl implements RunnerTestSuiteChunker {
+
+ /*
+ * The classes listed in this set has been chunked and its delegates has
+ * been created.
+ */
+ protected final Set<Class<?>> delegatesCreatedForTheseClasses = new LinkedHashSet<Class<?>>();
+
+ // A list of junit delegates.
+ protected final List<T> delegates = new ArrayList<T>();
+
+ protected volatile int testCount = NOT_INITIALIZED;
+
+ protected AbstractTestSuiteChunkerImpl(Class<?> testClass) throws Exception {
+ super(testClass);
+ }
+
+ protected AbstractTestSuiteChunkerImpl(Class<?>... testClasses) throws Exception {
+ super(testClasses);
+ }
+
+ protected Object getPowerMockTestListenersLoadedByASpecificClassLoader(Class<?> clazz, ClassLoader classLoader) {
+ try {
+ int defaultListenerSize = DEFAULT_TEST_LISTENERS_SIZE;
+ Class<?> annotationEnablerClass = null;
+ try {
+ annotationEnablerClass = Class.forName("org.powermock.api.extension.listener.AnnotationEnabler", false, classLoader);
+ } catch (ClassNotFoundException e) {
+ // Annotation enabler wasn't found in class path
+ defaultListenerSize = 0;
+ }
+
+ registerProxyframework(classLoader);
+
+ final Class<?> powerMockTestListenerType = Class.forName(PowerMockTestListener.class.getName(), false, classLoader);
+ Object testListeners = null;
+ if (clazz.isAnnotationPresent(PowerMockListener.class)) {
+ PowerMockListener annotation = clazz.getAnnotation(PowerMockListener.class);
+ final Class<? extends PowerMockTestListener>[] powerMockTestListeners = annotation.value();
+ if (powerMockTestListeners.length > 0) {
+ testListeners = Array.newInstance(powerMockTestListenerType, powerMockTestListeners.length + defaultListenerSize);
+ for (int i = 0; i < powerMockTestListeners.length; i++) {
+ String testListenerClassName = powerMockTestListeners[i].getName();
+ final Class<?> listenerTypeLoadedByClassLoader = Class.forName(testListenerClassName, false, classLoader);
+ Array.set(testListeners, i, Whitebox.newInstance(listenerTypeLoadedByClassLoader));
+ }
+ }
+ } else {
+ testListeners = Array.newInstance(powerMockTestListenerType, defaultListenerSize);
+ }
+
+ // Add default annotation enabler listener
+ if (annotationEnablerClass != null) {
+ Array.set(testListeners, Array.getLength(testListeners) - 1, Whitebox.newInstance(annotationEnablerClass));
+ }
+
+ return testListeners;
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("PowerMock internal error: Failed to load class.", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final void createTestDelegators(Class<?> testClass, List<TestChunk> chunks) throws Exception {
+ for (TestChunk chunk : chunks) {
+ ClassLoader classLoader = chunk.getClassLoader();
+ List<Method> methodsToTest = chunk.getTestMethodsToBeExecutedByThisClassloader();
+ T runnerDelegator = createDelegatorFromClassloader(classLoader, testClass, methodsToTest);
+ delegates.add(runnerDelegator);
+ }
+ delegatesCreatedForTheseClasses.add(testClass);
+ }
+
+ protected abstract T createDelegatorFromClassloader(ClassLoader classLoader, Class<?> testClass, final List<Method> methodsToTest)
+ throws Exception;
+
+ /**
+ * Get the internal test index for a junit runner delegate based on the
+ * "real" original test index. For example, the test may need to run a
+ * single test, for example the test with index 3. However since PowerMock
+ * may have chunked the test suite to use many classloaders and junit
+ * delegators the index (3) must be mapped to an internal representation for
+ * the specific junit runner delegate. This is what this method does. I.e.
+ * it will iterate through all junit runner delegates and see if they
+ * contain the test with index 3, in the internal index of this test
+ * delegator is returned.
+ *
+ * @param originalTestIndex
+ * The original test index as seen by the test runner.
+ * @return The internal test index as seen by PowerMock or <code>-1</code>
+ * if no index was found.
+ *
+ */
+ public int getInternalTestIndex(int originalTestIndex) {
+ Set<Entry<Integer, List<Integer>>> delegatorEntrySet = testAtDelegateMapper.entrySet();
+ for (Entry<Integer, List<Integer>> entry : delegatorEntrySet) {
+ final List<Integer> testIndexesForThisDelegate = entry.getValue();
+ final int internalIndex = testIndexesForThisDelegate.indexOf(originalTestIndex);
+ if (internalIndex != INTERNAL_INDEX_NOT_FOUND) {
+ return internalIndex;
+ }
+ }
+ return INTERNAL_INDEX_NOT_FOUND;
+ }
+
+ /**
+ * Get the junit runner delegate that handles the test at index
+ * <code>testIndex</code>. Throws a {@link RuntimeException} if a delegator
+ * is not found for the specific test index.
+ *
+ * @param testIndex
+ * The test index that a delegator should hold.
+ * @return The index for of the junit runner delegate as seen by JTestRack.
+ */
+ public int getDelegatorIndex(int testIndex) {
+ int delegatorIndex = -1;
+ Set<Entry<Integer, List<Integer>>> entrySet = testAtDelegateMapper.entrySet();
+ for (Entry<Integer, List<Integer>> entry : entrySet) {
+ // If the delegator contains the test case, return the index of the
+ // delegator.
+ if (entry.getValue().contains(testIndex)) {
+ delegatorIndex = entry.getKey();
+ break;
+ }
+ }
+
+ if (delegatorIndex == -1) {
+ throw new RuntimeException("Internal error: Failed to find the delgator index.");
+ }
+ return delegatorIndex;
+ }
+
+ public Class<?>[] getTestClasses() {
+ return testClasses;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ protected MockingFrameworkReporterFactory getFrameworkReporterFactory() {
+ Class<MockingFrameworkReporterFactory> mockingFrameworkReporterFactoryClass;
+ try {
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ mockingFrameworkReporterFactoryClass = (Class<MockingFrameworkReporterFactory>) classLoader.loadClass("org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl");
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(
+ "Extension API internal error: org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl could not be located in classpath.");
+ }
+
+ return Whitebox.newInstance(mockingFrameworkReporterFactoryClass);
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/ArrayMergerImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/ArrayMergerImpl.java
new file mode 100644
index 0000000..524717d
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/ArrayMergerImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.tests.utils.ArrayMerger;
+
+import java.lang.reflect.Array;
+
+/**
+ * The default implementation of the {@link ArrayMerger} interface.
+ */
+public class ArrayMergerImpl implements ArrayMerger {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T[] mergeArrays(Class<T> type, T[]... arraysToMerge) {
+ if (arraysToMerge == null || arraysToMerge.length == 0) {
+ return (T[]) Array.newInstance(type, 0);
+ }
+
+ int size = 0;
+ for (T[] array : arraysToMerge) {
+ if (array != null) {
+ size += array.length;
+ }
+ }
+
+ final T[] finalArray = (T[]) Array.newInstance(type, size);
+
+ int lastIndex = 0;
+ for (int i = 0; i < arraysToMerge.length; i++) {
+ final T[] currentArray = arraysToMerge[i];
+ if (currentArray != null) {
+ final int currentArrayLength = currentArray.length;
+ System.arraycopy(currentArray, 0, finalArray, lastIndex, currentArrayLength);
+ lastIndex += currentArrayLength;
+ }
+ }
+
+ return finalArray;
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/MockClassLoaderFactory.java b/core/src/main/java/org/powermock/tests/utils/impl/MockClassLoaderFactory.java
new file mode 100644
index 0000000..5ef28c6
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/MockClassLoaderFactory.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.classloader.annotations.UseClassPathAdjuster;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.impl.ClassMockTransformer;
+import org.powermock.core.transformers.impl.InterfaceMockTransformer;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ */
+class MockClassLoaderFactory {
+ private final String[] packagesToIgnore;
+ private final Class<?> testClass;
+ private final String[] classesToLoadByMockClassloader;
+ private final MockTransformer[] extraMockTransformers;
+
+ public MockClassLoaderFactory(Class<?> testClass, String[] classesToLoadByMockClassloader, String[] packagesToIgnore, MockTransformer... extraMockTransformers) {
+ this.testClass = testClass;
+ this.classesToLoadByMockClassloader = classesToLoadByMockClassloader;
+ this.packagesToIgnore = packagesToIgnore;
+ this.extraMockTransformers = extraMockTransformers;
+ }
+
+ public ClassLoader create() {
+ final String[] classesToLoadByMockClassloader = makeSureArrayContainsTestClassName(this.classesToLoadByMockClassloader, testClass.getName());
+
+ final ClassLoader mockLoader;
+ if (isContextClassLoaderShouldBeUsed(classesToLoadByMockClassloader)) {
+ mockLoader = Thread.currentThread().getContextClassLoader();
+ } else {
+ mockLoader = createMockClassLoader(classesToLoadByMockClassloader);
+ }
+ return mockLoader;
+ }
+
+ protected ClassLoader createMockClassLoader(final String[] classesToLoadByMockClassloader) {
+
+ List<MockTransformer> mockTransformerChain = getMockTransformers(extraMockTransformers);
+ final UseClassPathAdjuster useClassPathAdjuster = testClass.getAnnotation(UseClassPathAdjuster.class);
+
+ ClassLoader mockLoader = AccessController.doPrivileged(new PrivilegedAction<MockClassLoader>() {
+ @Override
+ public MockClassLoader run() {
+ return new MockClassLoader(classesToLoadByMockClassloader, packagesToIgnore, useClassPathAdjuster);
+ }
+ });
+
+ MockClassLoader mockClassLoader = (MockClassLoader) mockLoader;
+ mockClassLoader.setMockTransformerChain(mockTransformerChain);
+ new MockPolicyInitializerImpl(testClass).initialize(mockLoader);
+ return mockLoader;
+ }
+
+ protected boolean isContextClassLoaderShouldBeUsed(String[] classesToLoadByMockClassloader) {
+ return (classesToLoadByMockClassloader == null || classesToLoadByMockClassloader.length == 0) && !hasMockPolicyProvidedClasses(testClass);
+ }
+
+ protected List<MockTransformer> getMockTransformers(MockTransformer[] extraMockTransformers) {
+ List<MockTransformer> mockTransformerChain = new ArrayList<MockTransformer>();
+
+ mockTransformerChain.add(new ClassMockTransformer());
+ mockTransformerChain.add(new InterfaceMockTransformer());
+
+ Collections.addAll(mockTransformerChain, extraMockTransformers);
+ return mockTransformerChain;
+ }
+
+ private String[] makeSureArrayContainsTestClassName(String[] arrayOfClassNames, String testClassName) {
+ if (null == arrayOfClassNames || 0 == arrayOfClassNames.length) {
+ return new String[]{testClassName};
+
+ } else {
+ List<String> modifiedArrayOfClassNames = new ArrayList<String>(arrayOfClassNames.length + 1);
+ modifiedArrayOfClassNames.add(testClassName);
+ for (String className : arrayOfClassNames) {
+ if (testClassName.equals(className)) {
+ return arrayOfClassNames;
+ } else {
+ modifiedArrayOfClassNames.add(className);
+ }
+ }
+ return modifiedArrayOfClassNames.toArray(
+ new String[arrayOfClassNames.length + 1]);
+ }
+ }
+
+ /**
+ * @return <code>true</code> if there are some mock policies that
+ * contributes with classes that should be loaded by the mock
+ * classloader, <code>false</code> otherwise.
+ */
+ protected boolean hasMockPolicyProvidedClasses(Class<?> testClass) {
+ boolean hasMockPolicyProvidedClasses = false;
+ if (testClass.isAnnotationPresent(MockPolicy.class)) {
+ MockPolicy annotation = testClass.getAnnotation(MockPolicy.class);
+ Class<? extends PowerMockPolicy>[] value = annotation.value();
+ hasMockPolicyProvidedClasses = new MockPolicyInitializerImpl(value).needsInitialization();
+ }
+ return hasMockPolicyProvidedClasses;
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/MockPolicyInitializerImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/MockPolicyInitializerImpl.java
new file mode 100644
index 0000000..df2e853
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/MockPolicyInitializerImpl.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Map.Entry;
+
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.mockpolicies.impl.MockPolicyClassLoadingSettingsImpl;
+import org.powermock.mockpolicies.impl.MockPolicyInterceptionSettingsImpl;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.MockPolicyInitializer;
+
+/**
+ * The default implementation of the {@link MockPolicyInitializer} interface for
+ * mock policies.
+ */
+public class MockPolicyInitializerImpl implements MockPolicyInitializer {
+
+ private final PowerMockPolicy[] mockPolicies;
+ private final Class<? extends PowerMockPolicy>[] mockPolicyTypes;
+ private final Class<?> testClass;
+
+ public MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies) {
+ this(mockPolicies, false);
+ }
+
+ public MockPolicyInitializerImpl(Class<?> testClass) {
+ this(getMockPolicies(testClass), testClass, false);
+ }
+
+ private MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies, boolean internal) {
+ this(mockPolicies, null, false);
+ }
+
+ private MockPolicyInitializerImpl(Class<? extends PowerMockPolicy>[] mockPolicies, Class<?> testClass, boolean internal) {
+ this.testClass = testClass;
+ if (internal) {
+ mockPolicyTypes = null;
+ } else {
+ mockPolicyTypes = mockPolicies;
+ }
+ if (mockPolicies == null) {
+ this.mockPolicies = new PowerMockPolicy[0];
+ } else {
+ this.mockPolicies = new PowerMockPolicy[mockPolicies.length];
+ for (int i = 0; i < mockPolicies.length; i++) {
+ this.mockPolicies[i] = Whitebox.newInstance(mockPolicies[i]);
+ }
+ }
+ }
+
+ @Override
+ public boolean isPrepared(String fullyQualifiedClassName) {
+ MockPolicyClassLoadingSettings settings = getClassLoadingSettings();
+ final boolean foundInSuppressStaticInitializer = Arrays.binarySearch(settings.getStaticInitializersToSuppress(), fullyQualifiedClassName) < 0;
+ final boolean foundClassesLoadedByMockClassloader = Arrays.binarySearch(settings.getFullyQualifiedNamesOfClassesToLoadByMockClassloader(),
+ fullyQualifiedClassName) < 0;
+ return foundInSuppressStaticInitializer || foundClassesLoadedByMockClassloader;
+ }
+
+ @Override
+ public boolean needsInitialization() {
+ MockPolicyClassLoadingSettings settings = getClassLoadingSettings();
+ return settings.getStaticInitializersToSuppress().length > 0 || settings.getFullyQualifiedNamesOfClassesToLoadByMockClassloader().length > 0;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void initialize(ClassLoader classLoader) {
+ if (classLoader instanceof MockClassLoader) {
+ initialize((MockClassLoader) classLoader);
+ }
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ */
+ private void initialize(MockClassLoader classLoader) {
+ if (mockPolicies.length > 0) {
+ MockPolicyClassLoadingSettings classLoadingSettings = getClassLoadingSettings();
+ String[] fullyQualifiedNamesOfClassesToLoadByMockClassloader = classLoadingSettings
+ .getFullyQualifiedNamesOfClassesToLoadByMockClassloader();
+ classLoader.addClassesToModify(fullyQualifiedNamesOfClassesToLoadByMockClassloader);
+
+ if (testClass == null) {
+ throw new IllegalStateException("Internal error: testClass should never be null when calling initialize on a mock policy");
+ }
+
+ classLoader.addClassesToModify(testClass.getName());
+ Class<?>[] classes = testClass.getDeclaredClasses();
+ for (Class<?> clazz : classes) {
+ classLoader.addClassesToModify(clazz.getName());
+ }
+ Class<?>[] declaredClasses = testClass.getClasses();
+ for (Class<?> clazz : declaredClasses) {
+ classLoader.addClassesToModify(clazz.getName());
+ }
+
+ for (String string : classLoadingSettings.getStaticInitializersToSuppress()) {
+ classLoader.addClassesToModify(string);
+ MockRepository.addSuppressStaticInitializer(string);
+ }
+
+ invokeInitializeInterceptionSettingsFromClassLoader(classLoader);
+ }
+ }
+
+ @Override
+ public void refreshPolicies(ClassLoader classLoader) {
+ if (classLoader instanceof MockClassLoader) {
+ invokeInitializeInterceptionSettingsFromClassLoader((MockClassLoader) classLoader);
+ }
+ }
+
+ private void invokeInitializeInterceptionSettingsFromClassLoader(MockClassLoader classLoader) {
+ try {
+ final int sizeOfPolicies = mockPolicyTypes.length;
+ Object mockPolicies = Array.newInstance(Class.class, sizeOfPolicies);
+ for (int i = 0; i < sizeOfPolicies; i++) {
+ final Class<?> policyLoadedByClassLoader = Class.forName(mockPolicyTypes[i].getName(), false, classLoader);
+ Array.set(mockPolicies, i, policyLoadedByClassLoader);
+ }
+ final Class<?> thisTypeLoadedByMockClassLoader = Class.forName(this.getClass().getName(), false, classLoader);
+ Object mockPolicyHandler = Whitebox.invokeConstructor(thisTypeLoadedByMockClassLoader, mockPolicies, true);
+ Whitebox.invokeMethod(mockPolicyHandler, "initializeInterceptionSettings");
+ } catch (InvocationTargetException e) {
+ final Throwable targetException = e.getTargetException();
+ if (targetException instanceof RuntimeException) {
+ throw (RuntimeException) targetException;
+ } else if (targetException instanceof Error) {
+ throw (Error) targetException;
+ } else {
+ throw new RuntimeException(e);
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IllegalStateException("PowerMock internal error: Failed to load class.", e);
+ }
+ }
+
+ /*
+ * This method IS used, but it's invoked using reflection from the
+ * invokeInitializeInterceptionSettingsFromClassLoader method.
+ */
+ @SuppressWarnings("unused")
+ private void initializeInterceptionSettings() {
+ MockPolicyInterceptionSettings interceptionSettings = getInterceptionSettings();
+
+ for (Method method : interceptionSettings.getMethodsToSuppress()) {
+ MockRepository.addMethodToSuppress(method);
+ }
+
+ for (Entry<Method, InvocationHandler> entry : interceptionSettings.getProxiedMethods().entrySet()) {
+ MockRepository.putMethodProxy(entry.getKey(), entry.getValue());
+ }
+
+ for (Entry<Method, Object> entry : interceptionSettings.getStubbedMethods().entrySet()) {
+ final Method method = entry.getKey();
+ final Object className = entry.getValue();
+ MockRepository.putMethodToStub(method, className);
+ }
+
+ for (Field field : interceptionSettings.getFieldsToSuppress()) {
+ MockRepository.addFieldToSuppress(field);
+ }
+
+ for (String type : interceptionSettings.getFieldTypesToSuppress()) {
+ MockRepository.addFieldTypeToSuppress(type);
+ }
+ }
+
+ private MockPolicyInterceptionSettings getInterceptionSettings() {
+ MockPolicyInterceptionSettings settings = new MockPolicyInterceptionSettingsImpl();
+ for (PowerMockPolicy mockPolicy : mockPolicies) {
+ mockPolicy.applyInterceptionPolicy(settings);
+ }
+ return settings;
+ }
+
+ private MockPolicyClassLoadingSettings getClassLoadingSettings() {
+ MockPolicyClassLoadingSettings settings = new MockPolicyClassLoadingSettingsImpl();
+ for (PowerMockPolicy mockPolicy : mockPolicies) {
+ mockPolicy.applyClassLoadingPolicy(settings);
+ }
+ return settings;
+ }
+
+ /**
+ * Get the mock policies from a test-class.
+ */
+ @SuppressWarnings("unchecked")
+ private static Class<? extends PowerMockPolicy>[] getMockPolicies(Class<?> testClass) {
+ Class<? extends PowerMockPolicy>[] powerMockPolicies = new Class[0];
+ if (testClass.isAnnotationPresent(MockPolicy.class)) {
+ MockPolicy annotation = testClass.getAnnotation(MockPolicy.class);
+ powerMockPolicies = annotation.value();
+ }
+ return powerMockPolicies;
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImpl.java
new file mode 100644
index 0000000..e876ebc
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.tests.utils.IgnorePackagesExtractor;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.LinkedList;
+import java.util.List;
+
+public class PowerMockIgnorePackagesExtractorImpl implements IgnorePackagesExtractor {
+
+ @Override
+ public String[] getPackagesToIgnore(AnnotatedElement element) {
+ List<String> ignoredPackages = new LinkedList<String>();
+ PowerMockIgnore annotation = element.getAnnotation(PowerMockIgnore.class);
+ if (annotation != null) {
+ String[] ignores = annotation.value();
+ for (String ignorePackage : ignores) {
+ ignoredPackages.add(ignorePackage);
+ }
+ }
+ if (element instanceof Class<?>) {
+ Class<?> klazz = (Class<?>) element;
+ Class<?> superclass = klazz.getSuperclass();
+ if (superclass != null && !superclass.equals(Object.class)) {
+ String[] packagesToIgnore = getPackagesToIgnore(superclass);
+ for (String packageToIgnore : packagesToIgnore) {
+ ignoredPackages.add(packageToIgnore);
+ }
+ }
+ }
+ return ignoredPackages.toArray(new String[ignoredPackages.size()]);
+ }
+
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/PowerMockTestNotifierImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/PowerMockTestNotifierImpl.java
new file mode 100644
index 0000000..3d6fee6
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/PowerMockTestNotifierImpl.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.MockRepository;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.core.spi.testresult.Result;
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+import org.powermock.core.spi.testresult.impl.TestMethodResultImpl;
+import org.powermock.tests.utils.Keys;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+
+import java.lang.reflect.Method;
+
+/**
+ * Utility class that may be used by PowerMock test runners to notify listeners.
+ * Uses the {@link MockRepository} to set and get state.
+ */
+public class PowerMockTestNotifierImpl implements PowerMockTestNotifier {
+
+ private static final String ERROR_MESSAGE_TEMPLATE = "Invoking the %s method on PowerMock test listener %s failed.";
+
+ private final PowerMockTestListener[] powerMockTestListeners;
+
+ /**
+ * Create a new instance with the following parameters.
+ *
+ * @param powerMockTestListeners
+ * The PowerMock listeners that will be notified.
+ */
+ public PowerMockTestNotifierImpl(PowerMockTestListener[] powerMockTestListeners) {
+ if (powerMockTestListeners == null) {
+ this.powerMockTestListeners = new PowerMockTestListener[0];
+ } else {
+ this.powerMockTestListeners = powerMockTestListeners;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyAfterTestMethod(Object testInstance, Method method, Object[] arguments, TestMethodResult testResult) {
+ for (int i = 0; i < powerMockTestListeners.length; i++) {
+ final PowerMockTestListener testListener = powerMockTestListeners[i];
+ try {
+ testListener.afterTestMethod(testInstance, method, arguments, testResult);
+ } catch (Exception e) {
+ throw new RuntimeException(String.format(ERROR_MESSAGE_TEMPLATE, "afterTestMethod", testListener), e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyAfterTestSuiteEnded(Class<?> testClass, Method[] methods, TestSuiteResult testResult) {
+ for (PowerMockTestListener powerMockTestListener : powerMockTestListeners) {
+ try {
+ powerMockTestListener.afterTestSuiteEnded(testClass, methods, testResult);
+ } catch (Exception e) {
+ throw new RuntimeException(String.format(ERROR_MESSAGE_TEMPLATE, "afterTestSuiteEnded", powerMockTestListener), e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyBeforeTestMethod(Object testInstance, Method testMethod, Object[] arguments) {
+ MockRepository.putAdditionalState(Keys.CURRENT_TEST_INSTANCE, testInstance);
+ MockRepository.putAdditionalState(Keys.CURRENT_TEST_METHOD, testMethod);
+ MockRepository.putAdditionalState(Keys.CURRENT_TEST_METHOD_ARGUMENTS, arguments);
+ for (int i = 0; i < powerMockTestListeners.length; i++) {
+ final PowerMockTestListener testListener = powerMockTestListeners[i];
+ try {
+ testListener.beforeTestMethod(testInstance, testMethod, arguments);
+ } catch (Exception e) {
+ throw new RuntimeException(String.format(ERROR_MESSAGE_TEMPLATE, "beforeTestMethod", testListener), e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyBeforeTestSuiteStarted(Class<?> testClass, Method[] testMethods) {
+ for (PowerMockTestListener powerMockTestListener : powerMockTestListeners) {
+ try {
+ powerMockTestListener.beforeTestSuiteStarted(testClass, testMethods);
+ } catch (Exception e) {
+ throw new RuntimeException(String.format(ERROR_MESSAGE_TEMPLATE, "beforeTestSuiteStarted", powerMockTestListener), e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void notifyAfterTestMethod(boolean successful) {
+ final Object test = MockRepository.getAdditionalState(Keys.CURRENT_TEST_INSTANCE);
+ final Method testMethod = (Method) MockRepository.getAdditionalState(Keys.CURRENT_TEST_METHOD);
+ final Object[] testArguments = (Object[]) MockRepository.getAdditionalState(Keys.CURRENT_TEST_METHOD_ARGUMENTS);
+ final TestMethodResult testResult = new TestMethodResultImpl((successful ? Result.SUCCESSFUL : Result.FAILED));
+ notifyAfterTestMethod(test, testMethod, testArguments, testResult);
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImpl.java
new file mode 100644
index 0000000..465aeb6
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImpl.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.IndicateReloadClass;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
+import org.powermock.tests.utils.TestClassesExtractor;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Implementation of the {@link TestClassesExtractor} interface that extract
+ * classes from the {@link PrepareForTest} or {@link PrepareOnlyThisForTest}
+ * annotations. It also adds the test case to the array of classes that should
+ * be modified.
+ *
+ */
+public class PrepareForTestExtractorImpl extends AbstractTestClassExtractor {
+
+ public PrepareForTestExtractorImpl(){
+ this(false);
+ }
+
+ public PrepareForTestExtractorImpl(boolean includeMethods) {
+ super(includeMethods);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected String[] getClassesToModify(AnnotatedElement element) {
+ Set<String> all = new LinkedHashSet<String>();
+ addTestCase(all, element);
+ PrepareForTest prepareForTestAnnotation = element.getAnnotation(PrepareForTest.class);
+ PrepareOnlyThisForTest prepareOnlyThisForTestAnnotation = element.getAnnotation(PrepareOnlyThisForTest.class);
+ final boolean prepareForTestAnnotationPresent = prepareForTestAnnotation != null;
+ final boolean prepareOnlyThisForTestAnnotationPresent = prepareOnlyThisForTestAnnotation != null;
+
+ if (!prepareForTestAnnotationPresent && !prepareOnlyThisForTestAnnotationPresent) {
+ return null;
+ }
+
+ if (prepareForTestAnnotationPresent) {
+ final Class<?>[] classesToMock = prepareForTestAnnotation.value();
+ for (Class<?> classToMock : classesToMock) {
+ if (!classToMock.equals(IndicateReloadClass.class)) {
+ addClassHierarchy(all, classToMock);
+ }
+ }
+
+ addFullyQualifiedNames(all, prepareForTestAnnotation);
+ }
+
+ if (prepareOnlyThisForTestAnnotationPresent) {
+ final Class<?>[] classesToMock = prepareOnlyThisForTestAnnotation.value();
+ for (Class<?> classToMock : classesToMock) {
+ if (!classToMock.equals(IndicateReloadClass.class)) {
+ all.add(classToMock.getName());
+ }
+ }
+
+ addFullyQualifiedNames(all, prepareOnlyThisForTestAnnotation);
+ }
+
+ return all.toArray(new String[all.size()]);
+
+ }
+
+ private void addTestCase(Set<String> all, AnnotatedElement element) {
+ Class<?> testClass = null;
+ if (element instanceof Class<?>) {
+ testClass = (Class<?>) element;
+ } else if (element instanceof Method) {
+ testClass = ((Method) element).getDeclaringClass();
+ }
+ addClassHierarchy(all, testClass);
+ }
+
+ private void addFullyQualifiedNames(Set<String> all, PrepareForTest annotation) {
+ String[] fullyQualifiedNames = annotation.fullyQualifiedNames();
+ addFullyQualifiedNames(all, fullyQualifiedNames);
+ }
+
+ private void addFullyQualifiedNames(Set<String> all, PrepareOnlyThisForTest annotation) {
+ String[] fullyQualifiedNames = annotation.fullyQualifiedNames();
+ addFullyQualifiedNames(all, fullyQualifiedNames);
+ }
+
+ private void addFullyQualifiedNames(Set<String> all, String[] fullyQualifiedNames) {
+ for (String string : fullyQualifiedNames) {
+ if (!"".equals(string)) {
+ all.add(string);
+ }
+ }
+ }
+
+ private void addClassHierarchy(Set<String> all, Class<?> classToMock) {
+ while (classToMock != null && !classToMock.equals(Object.class)) {
+ addInnerClassesAndInterfaces(all, classToMock);
+ all.add(classToMock.getName());
+ classToMock = classToMock.getSuperclass();
+ }
+ }
+
+ private void addInnerClassesAndInterfaces(Set<String> all, Class<?> classToMock) {
+ Class<?>[] declaredClasses = classToMock.getDeclaredClasses();
+ for (Class<?> innerClass : declaredClasses) {
+ all.add(innerClass.getName());
+ }
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/StaticConstructorSuppressExtractorImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/StaticConstructorSuppressExtractorImpl.java
new file mode 100644
index 0000000..bdf623b
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/StaticConstructorSuppressExtractorImpl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.tests.utils.TestClassesExtractor;
+
+import java.lang.reflect.AnnotatedElement;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Implementation of the {@link TestClassesExtractor} interface for classes that
+ * should have their static initializers suppressed.
+ *
+ */
+public class StaticConstructorSuppressExtractorImpl extends AbstractTestClassExtractor {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String[] getClassesToModify(AnnotatedElement element) {
+ List<String> all = new LinkedList<String>();
+
+ final SuppressStaticInitializationFor suppressAnnotation = element.getAnnotation(SuppressStaticInitializationFor.class);
+
+ if (suppressAnnotation == null) {
+ return null;
+ } else {
+ final String[] value = suppressAnnotation.value();
+ for (String classToSuppress : value) {
+ if (!"".equals(classToSuppress)) {
+ all.add(classToSuppress);
+ MockRepository.addSuppressStaticInitializer(classToSuppress);
+ }
+ }
+ }
+
+ return all.toArray(new String[0]);
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/TestCaseEntry.java b/core/src/main/java/org/powermock/tests/utils/impl/TestCaseEntry.java
new file mode 100644
index 0000000..69c114a
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/TestCaseEntry.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.tests.utils.TestChunk;
+
+import java.util.List;
+
+/**
+ * A test case entry consists of a test class and a list of test chunks that
+ * should be executed for this entry.
+ */
+public class TestCaseEntry {
+
+ private final List<TestChunk> testChunks;
+ private final Class<?> testClass;
+
+ public TestCaseEntry(Class<?> testClass, List<TestChunk> chunks) {
+ this.testClass = testClass;
+ this.testChunks = chunks;
+ }
+
+ public List<TestChunk> getTestChunks() {
+ return testChunks;
+ }
+
+ public Class<?> getTestClass() {
+ return testClass;
+ }
+}
diff --git a/core/src/main/java/org/powermock/tests/utils/impl/TestChunkImpl.java b/core/src/main/java/org/powermock/tests/utils/impl/TestChunkImpl.java
new file mode 100644
index 0000000..68feb29
--- /dev/null
+++ b/core/src/main/java/org/powermock/tests/utils/impl/TestChunkImpl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.powermock.tests.utils.TestChunk;
+
+import java.lang.reflect.Method;
+import java.util.List;
+
+/**
+ * A test chunk consists of a list of methods that should be executed by a
+ * particular classloader.
+ */
+public class TestChunkImpl implements TestChunk {
+
+ private final ClassLoader classLoader;
+ private final List<Method> testMethodsToBeExecutedByThisClassloader;
+
+ public TestChunkImpl(ClassLoader classLoader, List<Method> testMethodsToBeExecutedByThisClassloader) {
+ this.classLoader = classLoader;
+ this.testMethodsToBeExecutedByThisClassloader = testMethodsToBeExecutedByThisClassloader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public List<Method> getTestMethodsToBeExecutedByThisClassloader() {
+ return testMethodsToBeExecutedByThisClassloader;
+ }
+
+ @Override
+ public boolean isMethodToBeExecutedByThisClassloader(Method method) {
+ return testMethodsToBeExecutedByThisClassloader.contains(method);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append("Classloader = ").append(classLoader).append("\n");
+ sb.append("Methods:\n");
+ for (Method method : testMethodsToBeExecutedByThisClassloader) {
+ sb.append(" ").append(method).append("\n");
+ }
+ return sb.toString();
+ }
+}
diff --git a/core/src/main/java/org/powermock/utils/ArrayUtil.java b/core/src/main/java/org/powermock/utils/ArrayUtil.java
new file mode 100644
index 0000000..edac26e
--- /dev/null
+++ b/core/src/main/java/org/powermock/utils/ArrayUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.utils;
+
+import java.lang.reflect.Array;
+
+/**
+ *
+ */
+public class ArrayUtil {
+
+ public static <T> T[] addAll(T[] array1, T[] array2) {
+ if (isEmpty(array1)) {
+ return clone(array2);
+ } else if (isEmpty(array2)) {
+ return clone(array1);
+ }
+ int newLength = array1.length + array2.length;
+ T[] joinedArray = createNewArrayWithSameType(array1, newLength);
+ System.arraycopy(array1, 0, joinedArray, 0, array1.length);
+ System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
+ return joinedArray;
+ }
+
+ private static <T> boolean isEmpty(T[] a) {
+ return a == null || a.length == 0;
+ }
+
+ private static <T> T[] clone(T[] array) {
+ if (array == null) {
+ return null;
+ }
+ return array.clone();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T> T[] createNewArrayWithSameType(T[] arrayPrototype, int newLength) {
+ return (T[]) Array.newInstance(arrayPrototype[0].getClass(), newLength);
+ }
+}
diff --git a/core/src/main/java/org/powermock/utils/StringJoiner.java b/core/src/main/java/org/powermock/utils/StringJoiner.java
new file mode 100644
index 0000000..f7bd8ad
--- /dev/null
+++ b/core/src/main/java/org/powermock/utils/StringJoiner.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.utils;
+
+/**
+ *
+ */
+public class StringJoiner {
+
+ private static final String LINE_SEPARATOR = System.lineSeparator();
+ private static final String EMPTY_STRING = "";
+
+
+ public static String join(Object... linesToBreak) {
+ StringBuilder out = new StringBuilder(LINE_SEPARATOR);
+ return join(out, linesToBreak);
+ }
+
+ private static String join(StringBuilder out, Object[] linesToBreak) {
+ for (Object line : linesToBreak) {
+ out.append(line.toString()).append(LINE_SEPARATOR);
+ }
+ int lastBreak = out.lastIndexOf(LINE_SEPARATOR);
+ return out.replace(lastBreak, lastBreak + 1, EMPTY_STRING).toString();
+ }
+
+}
diff --git a/core/src/test/java/org/powermock/WildcardMatcherTest.java b/core/src/test/java/org/powermock/WildcardMatcherTest.java
new file mode 100644
index 0000000..5e33a17
--- /dev/null
+++ b/core/src/test/java/org/powermock/WildcardMatcherTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock;
+
+import org.junit.Test;
+import org.powermock.core.WildcardMatcher;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class WildcardMatcherTest {
+
+ @Test
+ public void matchesWildcardOnBothEnds() throws Exception {
+ assertTrue(WildcardMatcher.matches("org.mytest.java", "*.java*"));
+ }
+
+ @Test
+ public void matchesWildcardSuffix() throws Exception {
+ assertTrue(WildcardMatcher.matches("org.mytest.java", "*.java"));
+ }
+
+ @Test
+ public void doesntMatchWildcardPrefix() throws Exception {
+ assertFalse(WildcardMatcher.matches("org.mytest.java", ".java*"));
+ }
+
+ @Test
+ public void convertsDotsAndWildcardsToRegExp() throws Exception {
+ assertFalse(WildcardMatcher.matches("javassist.runtime.Desc", "java.*"));
+ }
+
+ @Test
+ public void noWildcardCardPrefix() throws Exception {
+ assertFalse(WildcardMatcher.matches("org.mytest.java", ".java"));
+ }
+ @Test
+ public void exactMatch() throws Exception {
+ assertTrue(WildcardMatcher.matches("org.mytest.java", "org.mytest.java"));
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/classloader/Collaborator.java b/core/src/test/java/org/powermock/core/classloader/Collaborator.java
new file mode 100644
index 0000000..7cd80d2
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/classloader/Collaborator.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader;
+
+public class Collaborator {
+ private int count;
+
+ public void doStuff(int indx) {
+ count += indx;
+ }
+
+}
diff --git a/core/src/test/java/org/powermock/core/classloader/HardToTransform.java b/core/src/test/java/org/powermock/core/classloader/HardToTransform.java
new file mode 100644
index 0000000..ea8fb6b
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/classloader/HardToTransform.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader;
+
+public class HardToTransform {
+ public void run() {
+ Collaborator collaborator = new Collaborator();
+ for (int indx=0; indx<10; indx++) {
+ collaborator.doStuff(indx);
+ }
+ }
+ public int testInt() {
+ return 5;
+ }
+ public double testDouble() {
+ return 5;
+ }
+ public float testFloat() {
+ return 5;
+ }
+ public long testLong() {
+ return 5;
+ }
+ public short testShort() {
+ return 5;
+ }
+ public byte testByte() {
+ return 5;
+ }
+ public boolean testBoolean() {
+ return true;
+ }
+ public char testChar() {
+ return '5';
+ }
+
+ public String testString() {
+ return "5";
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/classloader/MockClassLoaderTest.java b/core/src/test/java/org/powermock/core/classloader/MockClassLoaderTest.java
new file mode 100644
index 0000000..e518c2e
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/classloader/MockClassLoaderTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.classloader;
+
+import javassist.ByteArrayClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import junit.framework.Assert;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.UseClassPathAdjuster;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.impl.ClassMockTransformer;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.*;
+import static org.powermock.core.classloader.MockClassLoader.MODIFY_ALL_CLASSES;
+
+public class MockClassLoaderTest {
+ @Test
+ public void autoboxingWorks() throws Exception {
+ String name = this.getClass().getPackage().getName() + ".HardToTransform";
+ final MockClassLoader mockClassLoader = new MockClassLoader(new String[]{name});
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+ Class<?> c = mockClassLoader.loadClass(name);
+
+ Object object = c.newInstance();
+ Whitebox.invokeMethod(object, "run");
+ Assert.assertEquals(5, Whitebox.invokeMethod(object, "testInt"));
+ Assert.assertEquals(5L, Whitebox.invokeMethod(object, "testLong"));
+ Assert.assertEquals(5f, Whitebox.invokeMethod(object, "testFloat"));
+ Assert.assertEquals(5.0, Whitebox.invokeMethod(object, "testDouble"));
+ Assert.assertEquals(new Short("5"), Whitebox.invokeMethod(object, "testShort"));
+ Assert.assertEquals(new Byte("5"), Whitebox.invokeMethod(object, "testByte"));
+ Assert.assertEquals(true, Whitebox.invokeMethod(object, "testBoolean"));
+ Assert.assertEquals('5', Whitebox.invokeMethod(object, "testChar"));
+ Assert.assertEquals("5", Whitebox.invokeMethod(object, "testString"));
+ }
+
+ @Test
+ public void callFindClassWorks() throws Exception {
+ MyClassloader myClassloader = new MyClassloader(new String[]{"org.mytest.myclass"});
+ assertEquals(String.class, myClassloader.findClassPublic("java.lang.String"));
+ }
+
+ @Test
+ public void prepareForTestHasPrecedenceOverPowerMockIgnoreAnnotatedPackages() throws Exception {
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[]{"org.mytest.myclass"});
+ Whitebox.setInternalState(mockClassLoader, new String[]{"*mytest*"}, DeferSupportingClassLoader.class);
+ assertTrue(Whitebox.<Boolean>invokeMethod(mockClassLoader, "shouldModify", "org.mytest.myclass"));
+ }
+
+ @Test
+ public void powerMockIgnoreAnnotatedPackagesAreIgnored() throws Exception {
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[]{"org.ikk.Jux"});
+ Whitebox.setInternalState(mockClassLoader, new String[]{"*mytest*"}, DeferSupportingClassLoader.class);
+ assertFalse(Whitebox.<Boolean>invokeMethod(mockClassLoader, "shouldModify", "org.mytest.myclass"));
+ }
+
+ @Test
+ public void powerMockIgnoreAnnotatedPackagesHavePrecedenceOverPrepareEverythingForTest() throws Exception {
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[]{MODIFY_ALL_CLASSES});
+ Whitebox.setInternalState(mockClassLoader, new String[]{"*mytest*"}, DeferSupportingClassLoader.class);
+ assertFalse(Whitebox.<Boolean>invokeMethod(mockClassLoader, "shouldModify", "org.mytest.myclass"));
+ }
+
+ @Test
+ public void prepareForTestPackagesArePrepared() throws Exception {
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[]{"*mytest*"});
+ assertTrue(Whitebox.<Boolean>invokeMethod(mockClassLoader, "shouldModify", "org.mytest.myclass"));
+ }
+
+ @Test
+ public void shouldAddIgnorePackagesToDefer() throws Exception {
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[0]);
+ mockClassLoader.addIgnorePackage("test*");
+ String[] deferPackages = Whitebox.<String[]>getInternalState(mockClassLoader, "deferPackages");
+ assertTrue(deferPackages.length > 1);
+ assertEquals("test*", deferPackages[deferPackages.length - 1]);
+ }
+
+ @Test
+ public void canFindResource() throws Exception {
+ final MockClassLoader mockClassLoader = new MockClassLoader(new String[0]);
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+
+ // Force a ClassLoader that can find 'foo/bar/baz/test.txt' into
+ // mockClassLoader.deferTo.
+ ResourcePrefixClassLoader resourcePrefixClassLoader = new ResourcePrefixClassLoader(
+ getClass().getClassLoader(), "org/powermock/core/classloader/");
+ mockClassLoader.deferTo = resourcePrefixClassLoader;
+
+ // MockClassLoader will only be able to find 'foo/bar/baz/test.txt' if it
+ // properly defers the resource lookup to its deferTo ClassLoader.
+ URL resource = mockClassLoader.getResource("foo/bar/baz/test.txt");
+ Assert.assertNotNull(resource);
+ Assert.assertTrue(resource.getPath().endsWith("test.txt"));
+ }
+
+ @Test
+ public void canFindResources() throws Exception {
+ final MockClassLoader mockClassLoader = new MockClassLoader(new String[0]);
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+
+ // Force a ClassLoader that can find 'foo/bar/baz/test.txt' into
+ // mockClassLoader.deferTo.
+ ResourcePrefixClassLoader resourcePrefixClassLoader = new ResourcePrefixClassLoader(
+ getClass().getClassLoader(), "org/powermock/core/classloader/");
+ mockClassLoader.deferTo = resourcePrefixClassLoader;
+
+ // MockClassLoader will only be able to find 'foo/bar/baz/test.txt' if it
+ // properly defers the resources lookup to its deferTo ClassLoader.
+ Enumeration<URL> resources = mockClassLoader.getResources("foo/bar/baz/test.txt");
+ Assert.assertNotNull(resources);
+ Assert.assertTrue(resources.hasMoreElements());
+ URL resource = resources.nextElement();
+ Assert.assertTrue(resource.getPath().endsWith("test.txt"));
+ Assert.assertFalse(resources.hasMoreElements());
+ }
+
+ @Test
+ public void resourcesNotDoubled() throws Exception {
+ final MockClassLoader mockClassLoader = new MockClassLoader(new String[0]);
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+
+ // MockClassLoader will only be able to find 'foo/bar/baz/test.txt' if it
+ // properly defers the resources lookup to its deferTo ClassLoader.
+ Enumeration<URL> resources = mockClassLoader.getResources("org/powermock/core/classloader/foo/bar/baz/test.txt");
+ Assert.assertNotNull(resources);
+ Assert.assertTrue(resources.hasMoreElements());
+ URL resource = resources.nextElement();
+ Assert.assertTrue(resource.getPath().endsWith("test.txt"));
+ Assert.assertFalse(resources.hasMoreElements());
+ }
+
+ @Test
+ public void canFindDynamicClassFromAdjustedClasspath() throws Exception {
+ // Construct MockClassLoader with @UseClassPathAdjuster annotation.
+ // It activates our MyClassPathAdjuster class which appends our dynamic
+ // class to the MockClassLoader's classpool.
+ UseClassPathAdjuster useClassPathAdjuster = new UseClassPathAdjuster() {
+ public Class<? extends Annotation> annotationType() {
+ return UseClassPathAdjuster.class;
+ }
+
+ public Class<? extends ClassPathAdjuster> value() {
+ return MyClassPathAdjuster.class;
+ }
+ };
+ final MockClassLoader mockClassLoader = new MockClassLoader(new String[0], useClassPathAdjuster);
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+
+ // setup custom classloader providing our dynamic class, for MockClassLoader to defer to
+ mockClassLoader.deferTo = new ClassLoader(getClass().getClassLoader()) {
+ @Override
+ public Class<?> loadClass(String name)
+ throws ClassNotFoundException {
+ if (name.equals(DynamicClassHolder.clazz.getName())) {
+ return DynamicClassHolder.clazz;
+ }
+ return super.loadClass(name);
+ }
+ };
+
+ // verify that MockClassLoader can successfully load the class
+ Class<?> dynamicTestClass = Class.forName(DynamicClassHolder.clazz.getName(), false, mockClassLoader);
+ Assert.assertNotNull(dynamicTestClass);
+ // .. and that MockClassLoader really loaded the class itself rather
+ // than just providing the class from the deferred classloader
+ assertNotSame(DynamicClassHolder.clazz, dynamicTestClass);
+ }
+
+ @Test(expected = ClassNotFoundException.class)
+ public void cannotFindDynamicClassInDeferredClassLoader() throws Exception {
+
+ MockClassLoader mockClassLoader = new MockClassLoader(new String[0]);
+ List<MockTransformer> list = new LinkedList<MockTransformer>();
+ list.add(new ClassMockTransformer());
+ mockClassLoader.setMockTransformerChain(list);
+
+ // setup custom classloader providing our dynamic class, for MockClassLoader to defer to
+ mockClassLoader.deferTo = new ClassLoader(getClass().getClassLoader()) {
+
+ @Override
+ public Class<?> loadClass(String name)
+ throws ClassNotFoundException {
+ return super.loadClass(name);
+ }
+ };
+
+ //Try to locate and load a class that is not in MockClassLoader.
+ Class<?> dynamicTestClass = Class.forName(DynamicClassHolder.clazz.getName(), false, mockClassLoader);
+
+ }
+
+ // helper class for canFindDynamicClassFromAdjustedClasspath()
+ static class MyClassPathAdjuster implements ClassPathAdjuster {
+ public void adjustClassPath(ClassPool classPool) {
+ classPool.appendClassPath(new ByteArrayClassPath(DynamicClassHolder.clazz.getName(), DynamicClassHolder.classBytes));
+ }
+ }
+
+ // helper class for canFindDynamicClassFromAdjustedClasspath()
+ static class DynamicClassHolder {
+ final static byte[] classBytes;
+ final static Class<?> clazz;
+
+ static {
+ try {
+ // construct a new class dynamically
+ ClassPool cp = ClassPool.getDefault();
+ final CtClass ctClass = cp.makeClass("my.ABCTestClass");
+ classBytes = ctClass.toBytecode();
+ clazz = ctClass.toClass();
+ } catch (Exception e) {
+ throw new RuntimeException("Problem constructing custom class", e);
+ }
+ }
+ }
+
+ static class MyClassloader extends MockClassLoader {
+
+ public MyClassloader(String[] classesToMock) {
+ super(classesToMock);
+ }
+
+ @Override
+ protected Class findClass(String name) throws ClassNotFoundException {
+ if (name.startsWith("java.lang")) {
+ return this.getClass().getClassLoader().loadClass(name);
+ }
+ return super.findClass(name);
+ }
+
+ public Class<?> findClassPublic(String s) throws ClassNotFoundException {
+ return findClass(s);
+ }
+ }
+
+}
diff --git a/core/src/test/java/org/powermock/core/classloader/ResourcePrefixClassLoader.java b/core/src/test/java/org/powermock/core/classloader/ResourcePrefixClassLoader.java
new file mode 100644
index 0000000..6f2e66f
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/classloader/ResourcePrefixClassLoader.java
@@ -0,0 +1,26 @@
+package org.powermock.core.classloader;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+public class ResourcePrefixClassLoader extends ClassLoader{
+
+ private final String prefix;
+
+ public ResourcePrefixClassLoader(ClassLoader parent, String prefix) {
+ super(parent);
+ this.prefix = prefix;
+ }
+
+ @Override
+ protected Enumeration<URL> findResources(String name) throws IOException {
+ // default super behaviour returns null, we want to delegate to our parent, with a prefix
+ return getParent().getResources(this.prefix + name);
+ }
+
+ @Override
+ protected URL findResource(String name) {
+ return getParent().getResource(this.prefix + name);
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupportTest.java b/core/src/test/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupportTest.java
new file mode 100644
index 0000000..296e18e
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/testlisteners/GlobalNotificationBuildSupportTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.testlisteners;
+
+import java.util.Collection;
+import java.util.concurrent.ConcurrentHashMap;
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.powermock.core.testlisteners.GlobalNotificationBuildSupport.Callback;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+/**
+ * The design of this test-class does only allow it to be run once per JVM
+ * (or more accurately "per classloader", in case the test-class is redefined
+ * by different classloaders in some sort of test suite),
+ * because it will test some class instantiation, which can only occur one per
+ * class.
+ */
+public class GlobalNotificationBuildSupportTest {
+
+ static boolean initiationOfNormalClassIsUnderWay;
+
+ static final Callback mockCallback = mock(Callback.class);
+
+ static class NormalClass {
+ static {
+ initiationOfNormalClassIsUnderWay = true;
+ GlobalNotificationBuildSupport.testClassInitiated(NormalClass.class);
+ }
+
+ NormalClass(String dummy) {
+ GlobalNotificationBuildSupport.testInstanceCreated(this);
+ }
+
+ public NormalClass() {
+ this("dummy");
+ GlobalNotificationBuildSupport.testInstanceCreated(this);
+ }
+ }
+
+ static class SubClass extends NormalClass {
+ public SubClass() {
+ super("dummy");
+ }
+ public SubClass(String dummy) {
+ }
+ }
+
+ private String nestedClassName(String localName) {
+ return GlobalNotificationBuildSupportTest.class.getName() + "$" + localName;
+ }
+
+ private void assertNotificationOf(NormalClass normalInstance) {
+ verify(mockCallback).testInstanceCreated(normalInstance);
+ verifyNoMoreInteractions(mockCallback);
+ }
+
+ @Test
+ public void normalClassCreation() {
+
+ // Given
+ assertFalse("Initiation of NormalClass must not yet have commenced",
+ initiationOfNormalClassIsUnderWay);
+ GlobalNotificationBuildSupport.prepareTestSuite(
+ nestedClassName("NormalClass"), mockCallback);
+
+ /* Nothing must have happened so far ... */
+ verifyNoMoreInteractions(mockCallback);
+
+ // When
+ final NormalClass normalInstance = new NormalClass();
+
+ // Then verify life-cycle callbacks on NormalClass
+ verify(mockCallback).suiteClassInitiated(NormalClass.class);
+
+ // Then notifications of created instances are expected ...
+ assertNotificationOf(normalInstance);
+ assertNotificationOf(new NormalClass());
+ assertNotificationOf(new NormalClass());
+ assertNotificationOf(new NormalClass("dummy"));
+ assertNotificationOf(new SubClass("dummy"));
+ assertNotificationOf(new NormalClass("dummy"));
+ assertNotificationOf(new SubClass("dummy"));
+ assertNotificationOf(new NormalClass());
+
+ // Tear-down
+ GlobalNotificationBuildSupport.closeTestSuite(NormalClass.class);
+ new NormalClass("dummy").toString();
+ new SubClass().hashCode();
+ verifyNoMoreInteractions(mockCallback); // Creation should no longer have any affect
+ }
+
+ /**
+ * Tests some ConcurrentHashMap functionality that
+ * {@link GlobalNotificationBuildSupport#closePendingTestSuites(java.lang.String)}
+ * depends on.
+ */
+ @Test
+ public void removeAllFromConcurrentHashMap() {
+ ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
+ final Object value = new Object();
+ map.put("foo", value);
+ map.put("bar", value);
+ assertEquals("Size of concurrent hashmap", 2, map.size());
+ Collection<?> valueToRemove = java.util.Collections.singleton(value);
+ map.values().removeAll(valueToRemove);
+ assertEquals("Size of concurrent hashmap after removal of values",
+ 0, map.size());
+ }
+
+ @AfterClass
+ public static void closeTestSuite() {
+ GlobalNotificationBuildSupport.closeTestSuite(NormalClass.class);
+ GlobalNotificationBuildSupport.closePendingTestSuites(mockCallback);
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/transformers/impl/ClassMockTransformerTest.java b/core/src/test/java/org/powermock/core/transformers/impl/ClassMockTransformerTest.java
new file mode 100644
index 0000000..b094f4f
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/transformers/impl/ClassMockTransformerTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.transformers.impl;
+
+import javassist.Modifier;
+import org.junit.Test;
+import org.powermock.core.IndicateReloadClass;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.transformers.MockTransformer;
+import powermock.test.support.ClassWithLargeMethods;
+import powermock.test.support.MainMockTransformerTestSupport.SupportClasses;
+
+import java.util.Collections;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+public class ClassMockTransformerTest {
+ /**
+ * This tests that a inner 'public static final class' can be modified to drop the final modifier. Fixes <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=95">Issue 95</a>.
+ */
+ @Test
+ public void staticFinalInnerClassesShouldBecomeNonFinal() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(SupportClasses.StaticFinalInnerClass.class.getName());
+ assertFalse(Modifier.isFinal(clazz.getModifiers()));
+ }
+
+ /**
+ * This tests that a inner 'public final class' can be modified to drop the final modifier. Fixes <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=95">Issue 95</a>.
+ */
+ @Test
+ public void finalInnerClassesShouldBecomeNonFinal() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(SupportClasses.FinalInnerClass.class.getName());
+ assertFalse(Modifier.isFinal(clazz.getModifiers()));
+ }
+
+ /**
+ * This tests that a inner 'enum' can be modified to drop the final modifier. Fixes <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=95">Issue 95</a>.
+ */
+ @Test
+ public void enumClassesShouldBecomeNonFinal() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(SupportClasses.EnumClass.class.getName());
+ assertFalse(Modifier.isFinal(clazz.getModifiers()));
+ }
+
+ @Test
+ public void privateInnerClassesShouldBecomeNonFinal() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(SupportClasses.class.getName() + "$PrivateStaticFinalInnerClass");
+ assertFalse(Modifier.isFinal(clazz.getModifiers()));
+ }
+
+ @Test
+ public void subclassShouldNormallyGetAnAdditionalDeferConstructor() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(SupportClasses.SubClass.class.getName());
+ assertEquals("Original number of constructoprs",
+ 1, SupportClasses.SubClass.class.getConstructors().length);
+ assertEquals("Number of constructors in modified class",
+ 2, clazz.getConstructors().length);
+ assertNotNull("Defer-constructor expected",
+ clazz.getConstructor(IndicateReloadClass.class));
+ }
+
+ @Test
+ public void shouldLoadClassWithMethodLowerThanJvmLimit() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(ClassWithLargeMethods.MethodLowerThanLimit.class.getName());
+ assertNotNull("Class has been loaded", clazz);
+ // There should be no exception since method was not overridden
+ clazz.getMethod("init").invoke(clazz);
+ }
+
+ @Test
+ public void shouldLoadClassAndOverrideMethodGreaterThanJvmLimit() throws Exception {
+ Class<?> clazz = loadWithMockClassLoader(ClassWithLargeMethods.MethodGreaterThanLimit.class.getName());
+ assertNotNull("Class has been loaded", clazz);
+ // There should be exception since method was overridden to satisfy JVM limit
+ try {
+ clazz.getMethod("init").invoke(clazz);
+ fail("Overridden method should throw exception");
+ } catch (Exception e) {
+ Throwable cause = e.getCause();
+ assertThat(cause, instanceOf(IllegalAccessException.class));
+ assertThat(cause.getMessage(),
+ containsString("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ private Class<?> loadWithMockClassLoader(String className) throws ClassNotFoundException {
+ MockClassLoader loader = new MockClassLoader(new String[]{MockClassLoader.MODIFY_ALL_CLASSES});
+ loader.setMockTransformerChain(Collections.<MockTransformer>singletonList(new ClassMockTransformer()));
+ return Class.forName(className, true, loader);
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/transformers/impl/TestClassTransformerTest.java b/core/src/test/java/org/powermock/core/transformers/impl/TestClassTransformerTest.java
new file mode 100644
index 0000000..d38c7aa
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/transformers/impl/TestClassTransformerTest.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.core.transformers.impl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.MockClassLoader;
+import powermock.test.support.MainMockTransformerTestSupport.SupportClasses;
+
+import org.powermock.core.IndicateReloadClass;
+
+import static java.lang.reflect.Modifier.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+ at RunWith(Parameterized.class)
+public class TestClassTransformerTest {
+
+ @Parameterized.Parameter(0)
+ public MockClassLoaderCase classLoaderCase;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> values() {
+ MockClassLoaderCase[] factoryAlternatives = MockClassLoaderCase.values();
+ List<Object[]> values = Arrays.asList(new Object[factoryAlternatives.length][]);
+ for (MockClassLoaderCase eachFactoryAlternative : factoryAlternatives) {
+ values.set(eachFactoryAlternative.ordinal(),
+ new Object[] {eachFactoryAlternative});
+ }
+ return values;
+ }
+
+ @Test
+ public void preparedSubclassShouldNotGetPublicDeferConstructor() throws Exception {
+ MockClassLoader mockClassLoader = classLoaderCase
+ .createMockClassLoaderThatPrepare(SupportClasses.SubClass.class);
+ final Class<?> clazz = Class.forName(SupportClasses.SubClass.class.getName(), true, mockClassLoader);
+ assertEquals("Original number of constructoprs",
+ 1, SupportClasses.SubClass.class.getConstructors().length);
+ try {
+ fail("A public defer-constructor is not expected: "
+ + clazz.getConstructor(IndicateReloadClass.class));
+ } catch (NoSuchMethodException is_expected) {}
+ assertEquals("Number of (public) constructors in modified class",
+ 1, clazz.getConstructors().length);
+
+ assertNotNull("But there should still be a non-public defer constructor!",
+ clazz.getDeclaredConstructor(IndicateReloadClass.class));
+ }
+
+ @Test
+ public void preparedClassConstructorsShouldKeepTheirAccessModifier() throws Exception {
+ MockClassLoader mockClassLoader = classLoaderCase
+ .createMockClassLoaderThatPrepare(SupportClasses.MultipleConstructors.class);
+ final Class<?> clazz = Class.forName(
+ SupportClasses.MultipleConstructors.class.getName(),
+ true, mockClassLoader);
+ for (Constructor<?> originalConstructor : SupportClasses
+ .MultipleConstructors.class.getDeclaredConstructors()) {
+ Class[] paramTypes = originalConstructor.getParameterTypes();
+ int originalModifiers = originalConstructor.getModifiers();
+ int newModifiers = clazz.getDeclaredConstructor(paramTypes).getModifiers();
+ String constructorName = 0 == paramTypes.length
+ ? "Default constructor "
+ : paramTypes[0].getSimpleName() + " constructor ";
+ assertEquals(constructorName + "is public?",
+ isPublic(originalModifiers), isPublic(newModifiers));
+ assertEquals(constructorName + "is protected?",
+ isProtected(originalModifiers), isProtected(newModifiers));
+ assertEquals(constructorName + "is private?",
+ isPrivate(originalModifiers), isPrivate(newModifiers));
+ }
+ }
+
+ enum MockClassLoaderCase {
+ WHEN_PREPARED_CLASS_IS_TESTCLASS {
+ @Override Class<?> chooseTestClass(Class<?> prepare4test) {
+ return prepare4test;
+ }
+ @Override String[] preparations(Class<?> prepare4test) {
+ return new String[] {MockClassLoader.MODIFY_ALL_CLASSES};
+ }
+ },
+ WHEN_ENCLOSING_CLASS_IS_TESTCLASS {
+ @Override Class<?> chooseTestClass(Class<?> prepare4test) {
+ return prepare4test.getDeclaringClass();
+ }
+ @Override String[] preparations(Class<?> prepare4test) {
+ return new String[] {prepare4test.getName()};
+ }
+ };
+
+ abstract Class<?> chooseTestClass(Class<?> prepare4test);
+ abstract String[] preparations(Class<?> prepare4test);
+
+ MockClassLoader createMockClassLoaderThatPrepare(Class<?> prepare4test) {
+ TestClassTransformer testClassTransformer = TestClassTransformer
+ .forTestClass(chooseTestClass(prepare4test))
+ .removesTestMethodAnnotation(Test.class)
+ .fromMethods(Collections.<Method>emptyList());
+ MockClassLoader mockClassLoader =
+ new MockClassLoader(preparations(prepare4test));
+ mockClassLoader.setMockTransformerChain(Arrays.asList(
+ new ClassMockTransformer(),
+ testClassTransformer));
+ return mockClassLoader;
+ }
+ }
+}
diff --git a/core/src/test/java/org/powermock/core/transformers/impl/TestPrimitives.java b/core/src/test/java/org/powermock/core/transformers/impl/TestPrimitives.java
new file mode 100644
index 0000000..fcac93c
--- /dev/null
+++ b/core/src/test/java/org/powermock/core/transformers/impl/TestPrimitives.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.core.transformers.impl;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import javassist.CtClass;
+import javassist.CtPrimitiveType;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(Parameterized.class)
+public class TestPrimitives {
+
+ final CtPrimitiveType ctType;
+
+ public TestPrimitives(CtPrimitiveType ctType) {
+ this.ctType = ctType;
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> values() throws Exception {
+ List<Object[]> valuesList = new ArrayList<Object[]>();
+ for (Field f : CtClass.class.getFields()) {
+ if (CtClass.class.isAssignableFrom(f.getType())) {
+ valuesList.add(new Object[] {f.get(null)});
+ }
+ }
+ return valuesList;
+ }
+
+ @Test
+ public void testMapping() {
+ Class<?> mapping = Primitives.getClassFor(ctType);
+ assertEquals("Mapping for ctType=" + ctType.getName(),
+ ctType.getSimpleName(), mapping.getSimpleName());
+ }
+}
diff --git a/core/src/test/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImplTest.java b/core/src/test/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImplTest.java
new file mode 100644
index 0000000..4e9d270
--- /dev/null
+++ b/core/src/test/java/org/powermock/tests/utils/impl/PowerMockIgnorePackagesExtractorImplTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+
+import static org.junit.Assert.assertEquals;
+
+public class PowerMockIgnorePackagesExtractorImplTest {
+
+ /**
+ * Makes sure that issue <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=150">150</a> is
+ * solved.
+ */
+ @Test
+ public void shouldFindIgnorePackagesInTheWholeClassHierarchy() throws Exception {
+ final PowerMockIgnorePackagesExtractorImpl tested = new PowerMockIgnorePackagesExtractorImpl();
+ final String[] packagesToIgnore = tested.getPackagesToIgnore(IgnoreAnnotatedDemoClass.class);
+ assertEquals(4, packagesToIgnore.length);
+ assertEquals("ignore0", packagesToIgnore[0]);
+ assertEquals("ignore1", packagesToIgnore[1]);
+ assertEquals("ignore2", packagesToIgnore[2]);
+ assertEquals("ignore3", packagesToIgnore[3]);
+ }
+
+ @PowerMockIgnore( { "ignore0", "ignore1" })
+ private class IgnoreAnnotatedDemoClass extends IgnoreAnnotatedDemoClassParent {
+
+ }
+
+ @PowerMockIgnore("ignore2")
+ private class IgnoreAnnotatedDemoClassParent extends IgnoreAnnotatedDemoClassGrandParent {
+
+ }
+
+ @PowerMockIgnore("ignore3")
+ private class IgnoreAnnotatedDemoClassGrandParent {
+
+ }
+}
diff --git a/core/src/test/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImplTest.java b/core/src/test/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImplTest.java
new file mode 100644
index 0000000..3c1fd46
--- /dev/null
+++ b/core/src/test/java/org/powermock/tests/utils/impl/PrepareForTestExtractorImplTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.tests.utils.impl;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.reflect.Whitebox;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests for the {@link PrepareForTestExtractorImpl} class.
+ *
+ */
+public class PrepareForTestExtractorImplTest {
+
+ /**
+ * Makes sure that issue <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=81">81</a> is
+ * solved.
+ */
+ @Test
+ public void assertThatInterfacesWorks() throws Exception {
+ final PrepareForTestExtractorImpl tested = new PrepareForTestExtractorImpl();
+ final Set<String> hashSet = new HashSet<String>();
+ Whitebox.invokeMethod(tested, "addClassHierarchy", hashSet, Serializable.class);
+ assertEquals(1, hashSet.size());
+ assertEquals(Serializable.class.getName(), hashSet.iterator().next());
+ }
+
+ /**
+ * Makes sure that issue <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=111">111</a> is
+ * solved.
+ */
+ @Test
+ public void shouldFindClassesToPrepareForTestInTheWholeClassHierarchy() throws Exception {
+ final PrepareForTestExtractorImpl tested = new PrepareForTestExtractorImpl();
+ final String[] classesToPrepare = tested.getTestClasses(PrepareForTestDemoClass.class);
+ assertEquals(8, classesToPrepare.length);
+ final String classPrefix = "Class";
+ final List<String> classesToPrepareList = Arrays.asList(classesToPrepare);
+ final int noOfClassesExplicitlyPrepared = 5;
+ for (int i = 0; i < noOfClassesExplicitlyPrepared; i++) {
+ final String className = classPrefix + (i + 1);
+ assertTrue("Should prepare " + className, classesToPrepareList.contains(className));
+ }
+ // We assert that the implicit classes (the test cases) are also added.
+ assertTrue(classesToPrepareList.contains(PrepareForTestDemoClass.class.getName()));
+ assertTrue(classesToPrepareList.contains(PrepareForTestDemoClassParent.class.getName()));
+ assertTrue(classesToPrepareList.contains(PrepareForTestDemoClassGrandParent.class.getName()));
+ }
+}
+
+ at PrepareForTest(fullyQualifiedNames = { "Class1", "Class2" })
+class PrepareForTestDemoClass extends PrepareForTestDemoClassParent {
+
+}
+
+ at PrepareForTest(fullyQualifiedNames = { "Class3" })
+class PrepareForTestDemoClassParent extends PrepareForTestDemoClassGrandParent {
+
+}
+
+ at PrepareForTest(fullyQualifiedNames = { "Class4", "Class5" })
+class PrepareForTestDemoClassGrandParent {
+
+}
\ No newline at end of file
diff --git a/core/src/test/java/powermock/test/support/ClassWithLargeMethods.java b/core/src/test/java/powermock/test/support/ClassWithLargeMethods.java
new file mode 100644
index 0000000..aa088d3
--- /dev/null
+++ b/core/src/test/java/powermock/test/support/ClassWithLargeMethods.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package powermock.test.support;
+
+public class ClassWithLargeMethods {
+
+ public static class MethodLowerThanLimit {
+ /**
+ * Method size after instrumentation is equal to 42989
+ */
+ public static String init() {
+ String a = "A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ return a;
+ }
+ }
+
+ public static class MethodGreaterThanLimit {
+ /**
+ * Method size after instrumentation is equal to 79522
+ */
+ public static String init() {
+ String a = "A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ String b = "B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";b+="B";
+ return a + b;
+ }
+ }
+}
diff --git a/core/src/test/java/powermock/test/support/MainMockTransformerTestSupport.java b/core/src/test/java/powermock/test/support/MainMockTransformerTestSupport.java
new file mode 100644
index 0000000..a2d26c2
--- /dev/null
+++ b/core/src/test/java/powermock/test/support/MainMockTransformerTestSupport.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.test.support;
+
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.transformers.impl.ClassMockTransformerTest;
+
+/**
+ * This class is used when running tests in {@link ClassMockTransformerTest}. It is
+ * placed in this package because classes in org.powermock.core.* are deferred by:
+ * {@link MockClassLoader#packagesToBeDeferred}. Additionally, the class must be modified when it is loaded, and as such
+ * not in {@link MockClassLoader#packagesToLoadButNotModify}.
+ */
+public class MainMockTransformerTestSupport {
+ public static class SupportClasses {
+ public final static class StaticFinalInnerClass {
+ }
+
+ public final static class FinalInnerClass {
+ }
+
+
+ private final static class PrivateStaticFinalInnerClass {
+ }
+
+ public enum EnumClass {
+ VALUE;
+ }
+
+ class SuperClass {
+ }
+
+ public class SubClass extends SuperClass {
+ public void dummyMethod() {}
+ }
+
+ public static class MultipleConstructors {
+
+ public MultipleConstructors() {}
+ protected MultipleConstructors(String s) {}
+ MultipleConstructors(int i) {}
+ private MultipleConstructors(Boolean[] array) {}
+ protected MultipleConstructors(int[] iarray, boolean b, String[] sarray) {}
+ }
+ }
+}
diff --git a/core/src/test/resources/org/powermock/core/classloader/foo/bar/baz/test.txt b/core/src/test/resources/org/powermock/core/classloader/foo/bar/baz/test.txt
new file mode 100644
index 0000000..5518faf
--- /dev/null
+++ b/core/src/test/resources/org/powermock/core/classloader/foo/bar/baz/test.txt
@@ -0,0 +1 @@
+This is the droid that you are looking for...
\ No newline at end of file
diff --git a/examples/AbstractFactory/pom.xml b/examples/AbstractFactory/pom.xml
new file mode 100644
index 0000000..f0284cb
--- /dev/null
+++ b/examples/AbstractFactory/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-abstractfactory</artifactId>
+ <name>AbstractFactory</name>
+
+ <description>
+ Example demonstrating how to mock a static call.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/AbstractFactory/src/main/java/powermock/examples/MyServiceUser.java b/examples/AbstractFactory/src/main/java/powermock/examples/MyServiceUser.java
new file mode 100644
index 0000000..6c0d24f
--- /dev/null
+++ b/examples/AbstractFactory/src/main/java/powermock/examples/MyServiceUser.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples;
+
+import powermock.examples.dependencymanagement.DependencyManager;
+import powermock.examples.domain.Person;
+import powermock.examples.service.MyService;
+
+import java.util.Set;
+
+/**
+ * A simple service class that uses the {@link DependencyManager} to get the
+ * {@link MyService} singleton instance. This is the class that we want to test.
+ * What's interesting in this example is the static call to the
+ * <code>DependencyManager</code>. Without byte-code manipulation (provided
+ * in this example by PowerMock) it would not be possible to return a mock from
+ * the call to
+ *
+ * <pre>
+ * DependencyManager.getInstance();
+ * </pre>
+ *
+ * The purpose of this example is to demonastrate how to mock that static
+ * method.
+ */
+public class MyServiceUser {
+
+ public int getNumberOfPersons() {
+ MyService myService = DependencyManager.getInstance().getMyService();
+ Set<Person> allPersons = myService.getAllPersons();
+ return allPersons.size();
+ }
+
+}
diff --git a/examples/AbstractFactory/src/main/java/powermock/examples/dependencymanagement/DependencyManager.java b/examples/AbstractFactory/src/main/java/powermock/examples/dependencymanagement/DependencyManager.java
new file mode 100644
index 0000000..7540173
--- /dev/null
+++ b/examples/AbstractFactory/src/main/java/powermock/examples/dependencymanagement/DependencyManager.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.dependencymanagement;
+
+import powermock.examples.service.MyService;
+import powermock.examples.service.impl.MyServiceImpl;
+
+/**
+ * This is a simple example of a factory class that provides dependencies that
+ * are shared by many classes (dependency lookup pattern). This approach is
+ * quite common when dependency injection is not used.
+ */
+public final class DependencyManager {
+
+ private static final DependencyManager instance = new DependencyManager();
+
+ private MyService myService;
+
+ private DependencyManager() {
+ }
+
+ public static DependencyManager getInstance() {
+ return instance;
+ }
+
+ public synchronized MyService getMyService() {
+ if (myService == null) {
+ myService = new MyServiceImpl();
+ }
+ return myService;
+ }
+}
diff --git a/examples/AbstractFactory/src/main/java/powermock/examples/domain/Person.java b/examples/AbstractFactory/src/main/java/powermock/examples/domain/Person.java
new file mode 100644
index 0000000..de706f7
--- /dev/null
+++ b/examples/AbstractFactory/src/main/java/powermock/examples/domain/Person.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.domain;
+
+/**
+ * A simple domain object.
+ */
+public class Person {
+
+ private String firstName;
+ private String lastName;
+ private String phoneNumber;
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getPhoneNumber() {
+ return phoneNumber;
+ }
+
+ public void setPhoneNumber(String phoneNumber) {
+ this.phoneNumber = phoneNumber;
+ }
+
+ public Person(String firstName, String lastName, String phoneNumber) {
+ super();
+ this.firstName = firstName;
+ this.lastName = lastName;
+ this.phoneNumber = phoneNumber;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
+ result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
+ result = prime * result + ((phoneNumber == null) ? 0 : phoneNumber.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Person other = (Person) obj;
+ if (firstName == null) {
+ if (other.firstName != null)
+ return false;
+ } else if (!firstName.equals(other.firstName))
+ return false;
+ if (lastName == null) {
+ if (other.lastName != null)
+ return false;
+ } else if (!lastName.equals(other.lastName))
+ return false;
+ if (phoneNumber == null) {
+ if (other.phoneNumber != null)
+ return false;
+ } else if (!phoneNumber.equals(other.phoneNumber))
+ return false;
+ return true;
+ }
+
+}
diff --git a/examples/AbstractFactory/src/main/java/powermock/examples/service/MyService.java b/examples/AbstractFactory/src/main/java/powermock/examples/service/MyService.java
new file mode 100644
index 0000000..8d494c9
--- /dev/null
+++ b/examples/AbstractFactory/src/main/java/powermock/examples/service/MyService.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.service;
+
+import powermock.examples.domain.Person;
+
+import java.util.Set;
+
+public interface MyService {
+
+ Set<Person> getAllPersons();
+
+}
\ No newline at end of file
diff --git a/examples/AbstractFactory/src/main/java/powermock/examples/service/impl/MyServiceImpl.java b/examples/AbstractFactory/src/main/java/powermock/examples/service/impl/MyServiceImpl.java
new file mode 100644
index 0000000..7d99d26
--- /dev/null
+++ b/examples/AbstractFactory/src/main/java/powermock/examples/service/impl/MyServiceImpl.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.service.impl;
+
+import powermock.examples.domain.Person;
+import powermock.examples.service.MyService;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class MyServiceImpl implements MyService {
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<Person> getAllPersons() {
+ return new HashSet<Person>();
+ }
+}
diff --git a/examples/AbstractFactory/src/test/java/powermock/examples/MyServiceUserTest.java b/examples/AbstractFactory/src/test/java/powermock/examples/MyServiceUserTest.java
new file mode 100644
index 0000000..81ff7ea
--- /dev/null
+++ b/examples/AbstractFactory/src/test/java/powermock/examples/MyServiceUserTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.dependencymanagement.DependencyManager;
+import powermock.examples.domain.Person;
+import powermock.examples.service.MyService;
+import powermock.examples.service.impl.MyServiceImpl;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This is an example unit test using JUnit 4.4 for the
+ * {@link MyServiceImpl#getAllPersons()} method. The task for PowerMock is to
+ * mock the call to {@link DependencyManager#getInstance()} which is not
+ * possible without byte-code manipulation.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(DependencyManager.class)
+public class MyServiceUserTest {
+
+ private MyServiceUser tested;
+
+ private DependencyManager dependencyManagerMock;
+ private MyService myServiceMock;
+
+ @Before
+ public void setUp() {
+ tested = new MyServiceUser();
+ dependencyManagerMock = createMock(DependencyManager.class);
+ myServiceMock = createMock(MyService.class);
+ }
+
+ @After
+ public void tearDown() {
+ tested = null;
+ dependencyManagerMock = null;
+ }
+
+ public void replayAll() throws Exception {
+ replay(DependencyManager.class, dependencyManagerMock, myServiceMock);
+ }
+
+ public void verifyAll() {
+ verify(DependencyManager.class, dependencyManagerMock, myServiceMock);
+ }
+
+ /**
+ * Unit test for the {@link MyServiceImpl#getAllPersons()} method. This
+ * tests demonstrate how to mock the static call to
+ * {@link DependencyManager#getInstance()} and returning a mock of the
+ * <code>DependencyManager</code> instead of the real instance.
+ */
+ @Test
+ public void testGetNumberOfPersons() throws Exception {
+ /*
+ * This is how to tell PowerMock to prepare the DependencyManager class
+ * for static mocking.
+ */
+ mockStatic(DependencyManager.class);
+
+ /*
+ * Expectations are performed the same for static methods as for
+ * instance methods.
+ */
+ expect(DependencyManager.getInstance()).andReturn(dependencyManagerMock);
+
+ expect(dependencyManagerMock.getMyService()).andReturn(myServiceMock);
+
+ Set<Person> persons = new HashSet<Person>();
+ persons.add(new Person("Johan", "Haleby", "MockStreet"));
+ persons.add(new Person("Jan", "Kronquist", "MockStreet2"));
+
+ expect(myServiceMock.getAllPersons()).andReturn(persons);
+
+ replayAll();
+
+ int numberOfPersons = tested.getNumberOfPersons();
+
+ verifyAll();
+
+ assertEquals(2, numberOfPersons);
+ }
+}
diff --git a/examples/ApacheCLIExample/pom.xml b/examples/ApacheCLIExample/pom.xml
new file mode 100644
index 0000000..267b63f
--- /dev/null
+++ b/examples/ApacheCLIExample/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-apachecli</artifactId>
+ <name>ApacheCLIExample</name>
+
+ <description>
+ Example showing PowerMock testing classes that extend Object.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>commons-cli</groupId>
+ <artifactId>commons-cli</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/ApacheCLIExample/src/main/java/powermock/examples/apachecli/OptionUser.java b/examples/ApacheCLIExample/src/main/java/powermock/examples/apachecli/OptionUser.java
new file mode 100644
index 0000000..24fc349
--- /dev/null
+++ b/examples/ApacheCLIExample/src/main/java/powermock/examples/apachecli/OptionUser.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.apachecli;
+
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+
+/**
+ * Class that verifies that the
+ * http://code.google.com/p/powermock/issues/detail?id=38 is fixed.
+ */
+public class OptionUser {
+
+ private Options options;
+
+ /**
+ * {@inheritDoc}
+ */
+ public void printOptionDescription() {
+ HelpFormatter formatter = new HelpFormatter();
+ formatter.printHelp("caption", options);
+ }
+}
diff --git a/examples/ApacheCLIExample/src/test/java/powermock/examples/apachecli/OptionUserTest.java b/examples/ApacheCLIExample/src/test/java/powermock/examples/apachecli/OptionUserTest.java
new file mode 100644
index 0000000..8ec9253
--- /dev/null
+++ b/examples/ApacheCLIExample/src/test/java/powermock/examples/apachecli/OptionUserTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.apachecli;
+
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Options;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import static org.easymock.EasyMock.*;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Verifies that the http://code.google.com/p/powermock/issues/detail?id=38 is
+ * fixed.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { OptionUser.class, HelpFormatter.class })
+public class OptionUserTest {
+
+ /**
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ @Test
+ public void testPrintOptionDescription() throws Exception {
+ HelpFormatter helpFormatterMock = PowerMock.createMockAndExpectNew(HelpFormatter.class);
+
+ helpFormatterMock.printHelp(eq("caption"), isA(Options.class));
+ expectLastCall().once();
+
+ OptionUser tested = new OptionUser();
+ Whitebox.setInternalState(tested, "options", new Options());
+
+ replay(helpFormatterMock, HelpFormatter.class);
+
+ tested.printOptionDescription();
+
+ verify(helpFormatterMock, HelpFormatter.class);
+ }
+}
diff --git a/examples/ApacheMina/pom.xml b/examples/ApacheMina/pom.xml
new file mode 100644
index 0000000..a9e3cf2
--- /dev/null
+++ b/examples/ApacheMina/pom.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-apachemina</artifactId>
+ <name>ApacheMina</name>
+
+ <description>
+ Examples showing PowerMock used to test NIO.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.mina</groupId>
+ <artifactId>mina-core</artifactId>
+ <version>2.0.0-M3</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareForTestAnnotationTest.java b/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareForTestAnnotationTest.java
new file mode 100644
index 0000000..e8b19bf
--- /dev/null
+++ b/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareForTestAnnotationTest.java
@@ -0,0 +1,40 @@
+package org.apache.mina.transport.socket.nio;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import java.util.concurrent.Executor;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertFalse;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This test validates that the {@link PrepareForTest} annotation modifies the
+ * class hierarchy and not only the specified classes.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { NioDatagramSession.class, NioProcessor.class })
+public class PrepareForTestAnnotationTest {
+
+ @Test
+ public void assertThatPrepareForTestModifiesClassHierarchy() throws Exception {
+ final String scheduleRemoveMethodName = "scheduleRemove";
+
+ Executor executor = createMock(Executor.class);
+ NioProcessor objectUnderTest = createPartialMock(NioProcessor.class, new String[] { scheduleRemoveMethodName }, executor);
+ NioDatagramSession session = createMock(NioDatagramSession.class);
+
+ expect(session.isConnected()).andReturn(false);
+ expectPrivate(objectUnderTest, scheduleRemoveMethodName, session).once();
+
+ replay(objectUnderTest, executor, session);
+
+ assertFalse((Boolean) Whitebox.invokeMethod(objectUnderTest, "flushNow", session, 20L));
+
+ verify(objectUnderTest, executor, session);
+ }
+}
diff --git a/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareOnlyThisForTestAnnotationTest.java b/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareOnlyThisForTestAnnotationTest.java
new file mode 100644
index 0000000..efb79fc
--- /dev/null
+++ b/examples/ApacheMina/src/test/java/org/apache/mina/transport/socket/nio/PrepareOnlyThisForTestAnnotationTest.java
@@ -0,0 +1,49 @@
+package org.apache.mina.transport.socket.nio;
+
+import org.apache.mina.core.session.AbstractIoSession;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import java.util.concurrent.Executor;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertFalse;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This test validates that the {@link PrepareOnlyThisForTest} annotation
+ * modifies the only the specified classes and not the full hierarchy.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareOnlyThisForTest( { NioDatagramSession.class, NioProcessor.class })
+public class PrepareOnlyThisForTestAnnotationTest {
+
+ @Test(expected = NullPointerException.class)
+ public void assertThatPrepareOnlyThisForTestDoesntModifyClassHierarchy() throws Exception {
+ NioDatagramSession session = createMock(NioDatagramSession.class);
+ expect(session.isConnected()).andReturn(false);
+ }
+
+ @Test
+ @PrepareOnlyThisForTest( { NioDatagramSession.class, NioProcessor.class, AbstractIoSession.class })
+ public void assertThatPrepareOnlyThisForTestWorks() throws Exception {
+ final String scheduleRemoveMethodName = "scheduleRemove";
+
+ Executor executor = createMock(Executor.class);
+ NioProcessor objectUnderTest = createPartialMock(NioProcessor.class, new String[] { scheduleRemoveMethodName }, executor);
+ NioDatagramSession session = createMock(NioDatagramSession.class);
+
+ expect(session.isConnected()).andReturn(false);
+ expectPrivate(objectUnderTest, scheduleRemoveMethodName, session).once();
+
+ replay(objectUnderTest, executor, session);
+
+ assertFalse(Whitebox.<Boolean> invokeMethod(objectUnderTest, "flushNow", session, 20L));
+
+ verify(objectUnderTest, executor, session);
+ }
+
+}
diff --git a/examples/DocumentationExamples/pom.xml b/examples/DocumentationExamples/pom.xml
new file mode 100644
index 0000000..d55c341
--- /dev/null
+++ b/examples/DocumentationExamples/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-documentationexamples</artifactId>
+ <name>DocumentationExamples</name>
+
+ <description>
+ Examples used to document various PowerMock features.
+ </description>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>cobertura-maven-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ </plugins>
+ </reporting>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/SomeService.java b/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/SomeService.java
new file mode 100644
index 0000000..67d569e
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/SomeService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased;
+
+import powermock.examples.annotationbased.dao.SomeDao;
+
+public class SomeService {
+
+ private final SomeDao someDao;
+
+ public SomeService(SomeDao someDao) {
+ if (someDao == null) {
+ throw new IllegalArgumentException("someDao cannot be null");
+ }
+ this.someDao = someDao;
+ }
+
+ public Object getData() {
+ return someDao.getSomeData();
+ }
+
+ public Object getMoreData() {
+ return someDao.getSomeOtherData();
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/dao/SomeDao.java b/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/dao/SomeDao.java
new file mode 100644
index 0000000..a58de27
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/annotationbased/dao/SomeDao.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased.dao;
+
+public class SomeDao {
+
+ public Object getSomeData() {
+ return new Object();
+ }
+
+ public Object getSomeOtherData() {
+ return new Object();
+ }
+
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportDao.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportDao.java
new file mode 100644
index 0000000..635a8c7
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportDao.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import powermock.examples.bypassencapsulation.nontest.Cache;
+import powermock.examples.bypassencapsulation.nontest.Injectable;
+import powermock.examples.bypassencapsulation.nontest.Report;
+
+/**
+ * A class used to demonstrate how it's possible for PowerMock to set internal
+ * state for a class that is also partially mocked.
+ */
+public class ReportDao {
+
+ @Injectable
+ private Cache cache;
+
+ public void deleteReport(final String reportName) {
+ Report report = getReportFromTargetName(reportName);
+ cache.invalidateCache(report);
+ // Imagine that we delete the report from some persistence storage.
+ }
+
+ private Report getReportFromTargetName(final String reportName) {
+ /* Imagine that this method does something that many methods share */
+ return null;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportGenerator.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportGenerator.java
new file mode 100644
index 0000000..90908b7
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ReportGenerator.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import powermock.examples.bypassencapsulation.nontest.Injectable;
+import powermock.examples.bypassencapsulation.nontest.Report;
+import powermock.examples.bypassencapsulation.nontest.ReportTemplateService;
+
+ at SuppressWarnings("unused")
+public class ReportGenerator {
+
+ @Injectable
+ private ReportTemplateService reportTemplateService;
+
+ public Report generateReport(String reportId) {
+ String templateId = reportTemplateService.getTemplateId(reportId);
+ /*
+ * Imagine some other code here that generates the report based on the
+ * template id.
+ */
+ return new Report("name");
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ServiceHolder.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ServiceHolder.java
new file mode 100644
index 0000000..fee049b
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/ServiceHolder.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Class whose purpose is the demonstrate how to use PowerMock to get and set
+ * internal state.
+ */
+public class ServiceHolder {
+
+ private final Set<Object> services = new HashSet<Object>();
+
+ public void addService(Object service) {
+ services.add(service);
+ }
+
+ public void removeService(Object service) {
+ services.remove(service);
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Cache.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Cache.java
new file mode 100644
index 0000000..05d00fe
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Cache.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation.nontest;
+
+/**
+ * A made-up class used to demonstrate some PowerMock functionality.
+ */
+public class Cache {
+
+ public void invalidateCache(final Report report) {
+ // Imagine something useful happening here.
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Injectable.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Injectable.java
new file mode 100644
index 0000000..cec11e9
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Injectable.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation.nontest;
+
+import java.lang.annotation.*;
+
+/**
+ * A custom marker annotation to demonstrate how to use PowerMock to set field
+ * dependencies. In a real application these dependencies are set by an external
+ * dependency injection framework using reflection.
+ */
+ at Target( { ElementType.FIELD, ElementType.CONSTRUCTOR })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface Injectable {
+
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Report.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Report.java
new file mode 100644
index 0000000..f59d0e3
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/Report.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation.nontest;
+
+/**
+ * A marker domain object used to demonstrate some test features in PowerMock.
+ */
+public class Report {
+ private String name;
+
+ public Report(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Report other = (Report) obj;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/ReportTemplateService.java b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/ReportTemplateService.java
new file mode 100644
index 0000000..b0716d9
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/bypassencapsulation/nontest/ReportTemplateService.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation.nontest;
+
+/**
+ * A stub service used to demonstrate test key-points.
+ */
+public class ReportTemplateService {
+
+ /**
+ * Get a template id from a report id.
+ *
+ * @param reportId
+ * The id of the report whose template to get.
+ * @return The Id of the template associated with the report.
+ */
+ public String getTemplateId(String reportId) {
+ return null;
+ }
+
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateFormatter.java b/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateFormatter.java
new file mode 100644
index 0000000..052340f
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateFormatter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.finalmocking;
+
+/**
+ * Simple class that uses a collaborator (the StateHolder class) which is final
+ * and have final methods. The purpose is to show that PowerMock has the ability
+ * to create a mock of the collaborator even though it's final and to expect the
+ * method calls even though they're also final.
+ */
+public class StateFormatter {
+
+ private final StateHolder stateHolder;
+
+ public StateFormatter(StateHolder stateHolder) {
+ this.stateHolder = stateHolder;
+ }
+
+ public String getFormattedState() {
+ String safeState = "State information is missing";
+ final String actualState = stateHolder.getState();
+ if (actualState != null) {
+ safeState = actualState;
+ }
+ return safeState;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateHolder.java b/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateHolder.java
new file mode 100644
index 0000000..b7daf29
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/finalmocking/StateHolder.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.finalmocking;
+
+/**
+ * A dummy class created to demonstrated how PowerMock can deal with final
+ * classes and methods.
+ */
+public final class StateHolder {
+
+ /**
+ * Dummy method that is used to demonstrate how PowerMock can deal with
+ * final methods.
+ *
+ * @return The current state.
+ */
+ public final String getState() {
+ // Imagine that we query a database for state
+ return null;
+ }
+
+ /**
+ * Dummy method that is used to demonstrate how PowerMock can deal with
+ * final methods.
+ */
+ public final void setState(String state) {
+ // Imagine that we store the state in a database.
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/DependencyUser.java b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/DependencyUser.java
new file mode 100644
index 0000000..19dd05f
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/DependencyUser.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy;
+
+import powermock.examples.mockpolicy.nontest.Dependency;
+import powermock.examples.mockpolicy.nontest.domain.DataObject;
+
+/**
+ * Very simple example of a class that uses a dependency.
+ */
+public class DependencyUser {
+
+ public DataObject getDependencyData() {
+ return new Dependency("some data").getData();
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/Dependency.java b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/Dependency.java
new file mode 100644
index 0000000..dbe53b0
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/Dependency.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy.nontest;
+
+import powermock.examples.mockpolicy.nontest.domain.DataObject;
+
+/**
+ * A simple class that demonstrates some of PowerMock's mock policy abilities.
+ */
+public class Dependency {
+
+ private final DataObject dataObject;
+
+ public Dependency(String data) {
+ dataObject = new DataObject(data);
+ }
+
+ public DataObject getData() {
+ return dataObject;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/domain/DataObject.java b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/domain/DataObject.java
new file mode 100644
index 0000000..4000088
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/nontest/domain/DataObject.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy.nontest.domain;
+
+/**
+ * A simple value object.
+ */
+public class DataObject {
+
+ private final String data;
+
+ public DataObject(String data) {
+ this.data = data;
+ }
+
+ public String getData() {
+ return data;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((data == null) ? 0 : data.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ DataObject other = (DataObject) obj;
+ if (data == null) {
+ if (other.data != null)
+ return false;
+ } else if (!data.equals(other.data))
+ return false;
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return data;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/policy/MyCustomMockPolicy.java b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/policy/MyCustomMockPolicy.java
new file mode 100644
index 0000000..f5a62eb
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/mockpolicy/policy/MyCustomMockPolicy.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy.policy;
+
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.mockpolicy.nontest.Dependency;
+import powermock.examples.mockpolicy.nontest.domain.DataObject;
+
+import java.lang.reflect.Method;
+
+/**
+ * A simple mock policy whose purpose is to intercept calls to
+ * {@link Dependency#getData()} and return a mock.
+ */
+public class MyCustomMockPolicy implements PowerMockPolicy {
+
+ /**
+ * Add the {@link Dependency} to the list of classes that should be loaded
+ * by the mock class-loader.
+ */
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(Dependency.class.getName());
+ }
+
+ /**
+ * Every time the {@link Dependency#getData()} method is invoked we return a
+ * custom instance of a {@link DataObject}.
+ */
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ final Method getDataMethod = Whitebox.getMethod(Dependency.class);
+ final DataObject dataObject = new DataObject("Policy generated data object");
+ settings.stubMethod(getDataMethod, dataObject);
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/newmocking/PersistenceManager.java b/examples/DocumentationExamples/src/main/java/powermock/examples/newmocking/PersistenceManager.java
new file mode 100644
index 0000000..01c3f30
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/newmocking/PersistenceManager.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.newmocking;
+
+import java.io.File;
+
+/**
+ * Used to demonstrate PowerMock's ability to mock new instance calls.
+ */
+public class PersistenceManager {
+
+ public boolean createDirectoryStructure(String directoryPath) {
+ File directory = new File(directoryPath);
+
+ if (directory.exists()) {
+ throw new IllegalArgumentException("\"" + directoryPath + "\" already exists.");
+ }
+
+ return directory.mkdirs();
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/EntityManager.java b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/EntityManager.java
new file mode 100644
index 0000000..208812b
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/EntityManager.java
@@ -0,0 +1,10 @@
+package powermock.examples.partialmocking;
+
+/**
+ * Created by Katharina Laube on 08.09.2014.
+ */
+public class EntityManager {
+ public void persist(Status status) {
+ // persist status
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/Status.java b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/Status.java
new file mode 100644
index 0000000..9212cfd
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/Status.java
@@ -0,0 +1,7 @@
+package powermock.examples.partialmocking;
+
+/**
+ * Created by Katharina Laube on 08.09.2014.
+ */
+public class Status {
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/StatusSender.java b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/StatusSender.java
new file mode 100644
index 0000000..f4495eb
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/partialmocking/StatusSender.java
@@ -0,0 +1,24 @@
+package powermock.examples.partialmocking;
+
+/**
+ * Used to demonstrate PowerMock's ability to partial mock method calls.
+ *
+ * Created by Katharina Laube on 08.09.2014.
+ */
+public class StatusSender {
+
+ EntityManager entityManager = new EntityManager();
+
+ public boolean handleStatus(Status status){
+
+ entityManager.persist(status);
+
+ return sendStatus(status);
+ }
+
+ public boolean sendStatus(Status status){
+ // code that will not be tested with handleStatus method
+ // (i.e. send status via a topic)
+ return false;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/privatemocking/DataService.java b/examples/DocumentationExamples/src/main/java/powermock/examples/privatemocking/DataService.java
new file mode 100644
index 0000000..0ecb9d4
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/privatemocking/DataService.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.privatemocking;
+
+/**
+ * A class used to demonstrate how it's possible for PowerMock to mock private
+ * methods invocations.
+ */
+public class DataService {
+
+
+
+ public boolean replaceData(final String dataId, final byte[] binaryData) {
+ return modifyData(dataId, binaryData);
+ }
+
+ public boolean deleteData(final String dataId) {
+ return modifyData(dataId, null);
+ }
+
+ /**
+ * Modify the data.
+ *
+ * @param dataId
+ * The ID of the data slot where the binary data will be stored.
+ * @param binaryData
+ * The binary data that will be stored. If <code>null</code>
+ * this means that the data for the particular slot is considered
+ * removed.
+ * @return <code>true</code> if the operation was successful,
+ * <code>false</code> otherwise.
+ */
+ private boolean modifyData(final String dataId, final byte[] binaryData) {
+ /*
+ * Imagine this method doing something complex and expensive.
+ */
+ return true;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/IdGenerator.java b/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/IdGenerator.java
new file mode 100644
index 0000000..e42ce8d
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.staticmocking;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/ServiceRegistrator.java b/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/ServiceRegistrator.java
new file mode 100644
index 0000000..9e1a11f
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/staticmocking/ServiceRegistrator.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.staticmocking;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ServiceRegistrator {
+
+ /**
+ * Holds all services that has been registered to this service registry.
+ */
+ private final Map<Long, Object> serviceRegistry = new HashMap<Long, Object>();
+
+ public long registerService(Object service) {
+ final long id = IdGenerator.generateNewId();
+ serviceRegistry.put(id, service);
+ return id;
+ }
+
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/EvilParent.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/EvilParent.java
new file mode 100644
index 0000000..14bfd2a
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/EvilParent.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructor;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress constructors.
+ */
+public class EvilParent {
+
+ public EvilParent() {
+ System.loadLibrary("evil.dll");
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructor.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructor.java
new file mode 100644
index 0000000..91e1cd5
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructor.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructor;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress an objects own
+ * constructor.
+ */
+public class ExampleWithEvilConstructor {
+
+ private final String message;
+
+ public ExampleWithEvilConstructor(String message) {
+ System.loadLibrary("evil.dll");
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilParent.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilParent.java
new file mode 100644
index 0000000..36252a9
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructor/ExampleWithEvilParent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructor;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress parent constructors.
+ */
+public class ExampleWithEvilParent extends EvilParent {
+
+ private final String message;
+
+ public ExampleWithEvilParent(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilGrandParent.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilGrandParent.java
new file mode 100644
index 0000000..eb21010
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilGrandParent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructorhierarchy;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress constructor
+ * hierarchies.
+ */
+public class EvilGrandParent {
+
+ public EvilGrandParent() {
+ System.loadLibrary("evil grand parent.dll");
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilParent.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilParent.java
new file mode 100644
index 0000000..aaf6299
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/EvilParent.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructorhierarchy;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress constructor
+ * hierarchies.
+ */
+public class EvilParent extends EvilGrandParent {
+
+ public EvilParent() {
+ System.loadLibrary("evil parent.dll");
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParent.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParent.java
new file mode 100644
index 0000000..12b57b2
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParent.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructorhierarchy;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress constructor hierarchies.
+ */
+public class ExampleWithEvilParentAndEvilGrandParent extends EvilParent {
+
+ private final String message;
+
+ public ExampleWithEvilParentAndEvilGrandParent(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/method/ExampleWithEvilMethod.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/method/ExampleWithEvilMethod.java
new file mode 100644
index 0000000..b520195
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/method/ExampleWithEvilMethod.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.method;
+
+/**
+ * This example demonstrates PowerMock abilities to suppress methods.
+ */
+public class ExampleWithEvilMethod {
+
+ private final String message;
+
+ public ExampleWithEvilMethod(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message + getEvilMessage();
+ }
+
+ private String getEvilMessage() {
+ System.loadLibrary("evil.dll");
+ return "evil!";
+ }
+}
diff --git a/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializer.java b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializer.java
new file mode 100644
index 0000000..3f9aa95
--- /dev/null
+++ b/examples/DocumentationExamples/src/main/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializer.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.staticinitializer;
+
+/**
+ * This class has a static initializers that needs to be removed in order to
+ * test the class.
+ */
+public class ExampleWithEvilStaticInitializer {
+
+ static {
+ System.loadLibrary("evil.dll");
+ }
+
+ private final String message;
+
+ public ExampleWithEvilStaticInitializer(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockAnnotationTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockAnnotationTest.java
new file mode 100644
index 0000000..12ecf3a
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockAnnotationTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.annotationbased.dao.SomeDao;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertSame;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Test of the {@link SomeService} when using the {@link Mock} annotation to
+ * create and inject mocks.
+ */
+ at RunWith(PowerMockRunner.class)
+public class UsingMockAnnotationTest {
+
+ @Mock
+ private SomeDao someDaoMock;
+
+ private SomeService someService;
+
+ @Before
+ public void setUp() {
+ someService = new SomeService(someDaoMock);
+ }
+
+ @Test
+ public void testGetData() throws Exception {
+ final Object data = new Object();
+ expect(someDaoMock.getSomeData()).andReturn(data);
+
+ replayAll();
+
+ assertSame(data, someService.getData());
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationTest.java
new file mode 100644
index 0000000..c81e288
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.annotationbased.dao.SomeDao;
+
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Test of the {@link SomeService} when using the {@link MockNice} annotation to
+ * create and inject mocks.
+ */
+ at RunWith(PowerMockRunner.class)
+public class UsingMockNiceAnnotationTest {
+
+ @MockNice
+ private SomeDao someDaoMock;
+
+ private SomeService someService;
+
+ @Before
+ public void setUp() {
+ someService = new SomeService(someDaoMock);
+ }
+
+ @Test
+ public void assertThatNiceMockAnnotationWork() throws Exception {
+ replayAll();
+
+ assertNull(someService.getData());
+ assertNull(someService.getMoreData());
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationToCreateAPartialMockTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationToCreateAPartialMockTest.java
new file mode 100644
index 0000000..169ea0a
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockNiceAnnotationToCreateAPartialMockTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.annotationbased.dao.SomeDao;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Test of the {@link SomeService} when using the {@link MockNice} annotation to
+ * create and inject mocks.
+ */
+ at RunWith(PowerMockRunner.class)
+public class UsingMockNiceAnnotationToCreateAPartialMockTest {
+
+ @MockNice("getSomeData")
+ private SomeDao someDaoMock;
+
+ private SomeService someService;
+
+ @Before
+ public void setUp() {
+ someService = new SomeService(someDaoMock);
+ }
+
+ @Test
+ public void assertThatNiceMockAnnotationWork() throws Exception {
+ replayAll();
+
+ assertNull(someService.getData());
+ assertEquals(Object.class, Whitebox.getType(someService.getMoreData()));
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockStrictAnnotationTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockStrictAnnotationTest.java
new file mode 100644
index 0000000..89003eb
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/annotationbased/UsingMockStrictAnnotationTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.MockStrict;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.annotationbased.dao.SomeDao;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertSame;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Test of the {@link SomeService} when using the {@link MockStrict} annotation
+ * to create and inject mocks.
+ */
+ at RunWith(PowerMockRunner.class)
+public class UsingMockStrictAnnotationTest {
+
+ @MockStrict
+ private SomeDao someDaoMock;
+
+ private SomeService someService;
+
+ @Before
+ public void setUp() {
+ someService = new SomeService(someDaoMock);
+ }
+
+ @Test
+ public void assertThatStrictMockAnnotationWork() throws Exception {
+ final Object dataObject = new Object();
+ final Object otherDataObject = new Object();
+ expect(someDaoMock.getSomeData()).andReturn(dataObject);
+ expect(someDaoMock.getSomeOtherData()).andReturn(otherDataObject);
+
+ replayAll();
+
+ assertSame(dataObject, someService.getData());
+ assertSame(otherDataObject, someService.getMoreData());
+
+ verifyAll();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void assertThatStrictMockAnnotationWorkWhenStrictMatchingIsNotApplied() throws Exception {
+ final Object dataObject = new Object();
+ final Object otherDataObject = new Object();
+ expect(someDaoMock.getSomeOtherData()).andReturn(otherDataObject);
+ expect(someDaoMock.getSomeData()).andReturn(dataObject);
+
+ replayAll();
+
+ assertSame(dataObject, someService.getData());
+ }
+
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportDaoTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportDaoTest.java
new file mode 100644
index 0000000..aed943f
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportDaoTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.bypassencapsulation.nontest.Cache;
+import powermock.examples.bypassencapsulation.nontest.Report;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit tests for the {@link ReportDao} class. This demonstrates one basic usage
+ * of PowerMock's ability to set internal state for a class that is partially
+ * mocked.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ReportDao.class)
+public class ReportDaoTest {
+
+ @Test
+ public void testDeleteReport() throws Exception {
+ final String getReportFromTargetNameMethodName = "getReportFromTargetName";
+ final String reportName = "reportName";
+ final Report report = new Report(reportName);
+
+ // Mock only the modifyData method
+ ReportDao tested = createPartialMock(ReportDao.class, getReportFromTargetNameMethodName);
+
+ // Create a mock of the distributed cache.
+ Cache cacheMock = createMock(Cache.class);
+
+ /*
+ * Now that we have a mock of the cache we need to set this instance in
+ * the class being tested.
+ */
+ Whitebox.setInternalState(tested, "cache", cacheMock);
+
+ /*
+ * Create an expectation for the private method
+ * "getReportFromTargetName".
+ */
+ expectPrivate(tested, getReportFromTargetNameMethodName, reportName).andReturn(report);
+
+ // Expect the call to invalidate cache.
+ cacheMock.invalidateCache(report);
+ expectLastCall().once();
+
+ replay(tested, cacheMock);
+
+ tested.deleteReport(reportName);
+
+ verify(tested, cacheMock);
+ }
+
+ @Test
+ public void testDeleteReport_usingPowerMock1Features() throws Exception {
+ final String getReportFromTargetNameMethodName = "getReportFromTargetName";
+ final String reportName = "reportName";
+ final Report report = new Report(reportName);
+
+ // Mock only the modifyData method
+ ReportDao tested = createPartialMock(ReportDao.class, getReportFromTargetNameMethodName);
+
+ // Create a mock of the distributed cache.
+ Cache cacheMock = createMock(Cache.class);
+
+ /*
+ * Now that we have a mock of the cache we need to set this instance in
+ * the class being tested.
+ */
+ Whitebox.setInternalState(tested, cacheMock);
+
+ /*
+ * Create an expectation for the private method
+ * "getReportFromTargetName".
+ */
+ expectPrivate(tested, getReportFromTargetNameMethodName, reportName).andReturn(report);
+
+ // Expect the call to invalidate cache.
+ cacheMock.invalidateCache(report);
+ expectLastCall().once();
+
+ replayAll();
+
+ tested.deleteReport(reportName);
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportGeneratorTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportGeneratorTest.java
new file mode 100644
index 0000000..ab2ac0b
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ReportGeneratorTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.bypassencapsulation.nontest.Report;
+import powermock.examples.bypassencapsulation.nontest.ReportTemplateService;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit test for the {@link ReportGenerator} class. Demonstrates the ability for
+ * PowerMock to easily set internal state of a class.
+ */
+public class ReportGeneratorTest {
+
+ @Test
+ public void testGenerateReport() throws Exception {
+ ReportGenerator tested = new ReportGenerator();
+ ReportTemplateService reportTemplateServiceMock = createMock(ReportTemplateService.class);
+
+ Whitebox.setInternalState(tested, "reportTemplateService", reportTemplateServiceMock);
+
+ final String reportId = "id";
+ expect(reportTemplateServiceMock.getTemplateId(reportId)).andReturn("templateId");
+
+ replay(reportTemplateServiceMock);
+
+ Report actualReport = tested.generateReport(reportId);
+
+ verify(reportTemplateServiceMock);
+
+ assertEquals(new Report("name"), actualReport);
+ }
+
+ @Test
+ public void testGenerateReport_usingFieldTypeAppraoch() throws Exception {
+ ReportGenerator tested = new ReportGenerator();
+ ReportTemplateService reportTemplateServiceMock = createMock(ReportTemplateService.class);
+
+ Whitebox.setInternalState(tested, reportTemplateServiceMock);
+
+ final String reportId = "id";
+ expect(reportTemplateServiceMock.getTemplateId(reportId)).andReturn("templateId");
+
+ replay(reportTemplateServiceMock);
+
+ Report actualReport = tested.generateReport(reportId);
+
+ verify(reportTemplateServiceMock);
+
+ assertEquals(new Report("name"), actualReport);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ServiceHolderTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ServiceHolderTest.java
new file mode 100644
index 0000000..6d4bc4b
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/bypassencapsulation/ServiceHolderTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.bypassencapsulation;
+
+import org.junit.Test;
+
+import java.util.Set;
+
+import static org.junit.Assert.*;
+import static org.powermock.reflect.Whitebox.getInternalState;
+
+/**
+ * Unit tests for the {@link ServiceHolder} class.
+ */
+ at SuppressWarnings("unchecked")
+public class ServiceHolderTest {
+
+ @Test
+ public void testAddService() throws Exception {
+ ServiceHolder tested = new ServiceHolder();
+ final Object service = new Object();
+
+ tested.addService(service);
+
+ Set<String> services = (Set<String>) getInternalState(tested, "services");
+
+ assertEquals("Size of the \"services\" Set should be 1", 1, services.size());
+ assertSame("The services Set should didn't contain the expect service", service, services.iterator().next());
+ }
+
+ @Test
+ public void testRemoveService() throws Exception {
+ ServiceHolder tested = new ServiceHolder();
+ final Object service = new Object();
+
+ // Get the hash set.
+ Set<Object> servicesSet = (Set<Object>) getInternalState(tested, "services");
+ servicesSet.add(service);
+
+ tested.removeService(service);
+
+ assertTrue("Set should be empty after removeal.", servicesSet.isEmpty());
+ }
+
+ @Test
+ public void testRemoveService_fieldTypeApproach() throws Exception {
+ ServiceHolder tested = new ServiceHolder();
+ final Object service = new Object();
+
+ // Get the hash set.
+ Set<Object> servicesSet = getInternalState(tested, Set.class);
+ servicesSet.add(service);
+
+ tested.removeService(service);
+
+ assertTrue("Set should be empty after removeal.", servicesSet.isEmpty());
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/finalmocking/StateFormatterTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/finalmocking/StateFormatterTest.java
new file mode 100644
index 0000000..bcc8582
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/finalmocking/StateFormatterTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.finalmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit tests of the {@link StateFormatter} class.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StateHolder.class)
+public class StateFormatterTest {
+
+ @Test
+ public void testGetFormattedState_actualStateExists() throws Exception {
+ final String expectedState = "state";
+
+ StateHolder stateHolderMock = createMock(StateHolder.class);
+ StateFormatter tested = new StateFormatter(stateHolderMock);
+
+ expect(stateHolderMock.getState()).andReturn(expectedState);
+
+ replay(stateHolderMock);
+
+ final String actualState = tested.getFormattedState();
+
+ verify(stateHolderMock);
+
+ assertEquals(expectedState, actualState);
+ }
+
+ @Test
+ public void testGetFormattedState_noStateExists() throws Exception {
+ final String expectedState = "State information is missing";
+
+ StateHolder stateHolderMock = createMock(StateHolder.class);
+ StateFormatter tested = new StateFormatter(stateHolderMock);
+
+ expect(stateHolderMock.getState()).andReturn(null);
+
+ replay(stateHolderMock);
+
+ final String actualState = tested.getFormattedState();
+
+ verify(stateHolderMock);
+
+ assertEquals(expectedState, actualState);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/DependencyUserTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/DependencyUserTest.java
new file mode 100644
index 0000000..e621a00
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/DependencyUserTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.mockpolicy.nontest.domain.DataObject;
+import powermock.examples.mockpolicy.policy.MyCustomMockPolicy;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that makes sure that {@link MyCustomMockPolicy} works.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(MyCustomMockPolicy.class)
+public class DependencyUserTest {
+
+ @Test
+ public void assertThatMyFirstMockPolicyWork() throws Exception {
+ DataObject dependencyData = new DependencyUser().getDependencyData();
+ assertEquals("Policy generated data object", dependencyData.getData());
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/SeveralMockPolicyMethodsTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/SeveralMockPolicyMethodsTest.java
new file mode 100644
index 0000000..0115644
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/mockpolicy/SeveralMockPolicyMethodsTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.mockpolicy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.mockpolicy.nontest.domain.DataObject;
+import powermock.examples.mockpolicy.policy.MyCustomMockPolicy;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Test that makes sure that {@link MyCustomMockPolicy} works when several test
+ * methods are used. This was a bug fixed in PowerMock 1.3.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(MyCustomMockPolicy.class)
+public class SeveralMockPolicyMethodsTest {
+
+ /**
+ * Make sure that mock policies works in setup methods.
+ */
+ @Before
+ public void setUp() {
+ DataObject dependencyData = new DependencyUser().getDependencyData();
+ assertEquals("Policy generated data object", dependencyData.getData());
+ }
+
+ @Test
+ public void assertThatMyFirstMockPolicyWork() throws Exception {
+ DataObject dependencyData = new DependencyUser().getDependencyData();
+ assertEquals("Policy generated data object", dependencyData.getData());
+ }
+
+ @Test
+ public void assertThatMyFirstMockPolicyWorkFromAnotherTestMethodInTheSameTestClass() throws Exception {
+ DataObject dependencyData = new DependencyUser().getDependencyData();
+ assertEquals("Policy generated data object", dependencyData.getData());
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerTest.java
new file mode 100644
index 0000000..7a23ffb
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.newmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.io.File;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit test for the {@link PersistenceManager} class that demonstrates
+ * PowerMock's ability to mock new instance calls.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PersistenceManager.class)
+public class PersistenceManagerTest {
+
+ @Test
+ public void testCreateDirectoryStructure_ok() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = createMock(File.class);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expectNew(File.class, path).andReturn(fileMock);
+
+ expect(fileMock.exists()).andReturn(false);
+ expect(fileMock.mkdirs()).andReturn(true);
+
+ replay(fileMock, File.class);
+
+ assertTrue(tested.createDirectoryStructure(path));
+
+ verify(fileMock, File.class);
+ }
+
+ @Test
+ public void testCreateDirectoryStructure_usingCreateMockAndExpectNew() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = createMockAndExpectNew(File.class, path);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expect(fileMock.exists()).andReturn(false);
+ expect(fileMock.mkdirs()).andReturn(true);
+
+ replay(fileMock, File.class);
+
+ assertTrue(tested.createDirectoryStructure(path));
+
+ verify(fileMock, File.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateDirectoryStructure_fails() throws Exception {
+ final String path = "directoryPath";
+ File mFileMock = createMock(File.class);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expectNew(File.class, path).andReturn(mFileMock);
+
+ expect(mFileMock.exists()).andReturn(true);
+
+ replay(mFileMock, File.class);
+
+ tested.createDirectoryStructure(path);
+
+ verify(mFileMock, File.class);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerWithReplayAllAndVerifyAllTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerWithReplayAllAndVerifyAllTest.java
new file mode 100644
index 0000000..5fec38e
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/newmocking/PersistenceManagerWithReplayAllAndVerifyAllTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.newmocking;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.io.File;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit test for the {@link PersistenceManager} class that demonstrates
+ * PowerMock's ability to mock new instance calls.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PersistenceManager.class)
+public class PersistenceManagerWithReplayAllAndVerifyAllTest {
+
+ @Test
+ public void testCreateDirectoryStructure_ok() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = createMock(File.class);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expectNew(File.class, path).andReturn(fileMock);
+
+ expect(fileMock.exists()).andReturn(false);
+ expect(fileMock.mkdirs()).andReturn(true);
+
+ replayAll();
+
+ assertTrue(tested.createDirectoryStructure(path));
+
+ verifyAll();
+ }
+
+ @Test
+ public void testCreateDirectoryStructure_ok_usingEasyMockToCreateTheFileMock() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = EasyMock.createMock(File.class);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expectNew(File.class, path).andReturn(fileMock);
+
+ expect(fileMock.exists()).andReturn(false);
+ expect(fileMock.mkdirs()).andReturn(true);
+
+ replayAll(fileMock);
+
+ assertTrue(tested.createDirectoryStructure(path));
+
+ verifyAll();
+ }
+
+
+ @Test
+ public void testCreateDirectoryStructure_usingCreateMockAndExpectNew() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = createMockAndExpectNew(File.class, path);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expect(fileMock.exists()).andReturn(false);
+ expect(fileMock.mkdirs()).andReturn(true);
+
+ replayAll();
+
+ assertTrue(tested.createDirectoryStructure(path));
+
+ verifyAll();
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateDirectoryStructure_fails() throws Exception {
+ final String path = "directoryPath";
+ File fileMock = createMock(File.class);
+
+ PersistenceManager tested = new PersistenceManager();
+
+ expectNew(File.class, path).andReturn(fileMock);
+
+ expect(fileMock.exists()).andReturn(true);
+
+ replayAll();
+
+ tested.createDirectoryStructure(path);
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/partialmocking/StatusSenderTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/partialmocking/StatusSenderTest.java
new file mode 100644
index 0000000..2d34151
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/partialmocking/StatusSenderTest.java
@@ -0,0 +1,51 @@
+package powermock.examples.partialmocking;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Used to demonstrate PowerMock's ability to partial mock method calls.
+ * Simple exmaple without private method mocking.
+ *
+ * Created by Katharina Laube on 08.09.2014.
+ */
+public class StatusSenderTest {
+
+ private StatusSender tested;
+ private EntityManager entityManager;
+
+ @Before
+ public void setUp() throws Exception {
+
+ /* Mock only the sendStatus method.
+ (This mock creation should be moved to the test method,
+ when method sendStatus is tested as well.)
+ */
+ tested = createPartialMock(StatusSender.class, "sendStatus");
+
+ // Mock all methods of entityManager
+ entityManager = createMock(EntityManager.class);
+ tested.entityManager = entityManager;
+ }
+
+ @Test
+ public void testHandleStatus() throws Exception {
+ Status status = new Status();
+
+ // expect call of void method from EntityManager
+ entityManager.persist(status);
+
+ /* expect call of another method in the tested class
+ which will be tested separately. */
+ expect(tested.sendStatus(status)).andReturn(true);
+
+ replayAll();
+
+ tested.handleStatus(status);
+
+ verifyAll();
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/privatemocking/DataServiceTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/privatemocking/DataServiceTest.java
new file mode 100644
index 0000000..f6f5cd2
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/privatemocking/DataServiceTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.privatemocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit tests for the {@link DataService} class. This demonstrates one basic
+ * usage of PowerMock's ability for partial mocking as well as expecting a
+ * private method.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(DataService.class)
+public class DataServiceTest {
+
+ @Test
+ public void testReplaceData() throws Exception {
+ final String modifyDataMethodName = "modifyData";
+ final byte[] expectedBinaryData = new byte[] { 42 };
+ final String expectedDataId = "id";
+
+ // Mock only the modifyData method
+ DataService tested = createPartialMock(DataService.class, modifyDataMethodName);
+
+ /*
+ * This is the simplest way to expect a non-void method call to a
+ * private method using PowerMock. You simply supply the instance under
+ * test as the first parameter followed by the method name of the method
+ * to expect. The last two parameters are simply the method arguments
+ * that should be expected when invoking the method.
+ */
+ expectPrivate(tested, modifyDataMethodName, expectedDataId,
+ expectedBinaryData).andReturn(true);
+
+ replay(tested);
+
+ assertTrue(tested.replaceData(expectedDataId, expectedBinaryData));
+
+ verify(tested);
+ }
+
+ @Test
+ public void testDeleteData() throws Exception {
+ final String modifyDataMethodName = "modifyData";
+ final byte[] expectedBinaryData = null;
+ final String expectedDataId = "id";
+
+ // Mock only the modifyData method
+ DataService tested = createPartialMock(DataService.class, modifyDataMethodName);
+
+ /*
+ * This is the simplest way to expect a non-void method call to a
+ * private method using PowerMock. You simply supply the instance under
+ * test as the first parameter followed by the method name of the method
+ * to expect. The last two parameters are simply the method arguments
+ * that should be expected when invoking the method.
+ */
+ expectPrivate(tested, modifyDataMethodName, expectedDataId,
+ expectedBinaryData).andReturn(true);
+
+ replay(tested);
+
+ assertTrue(tested.deleteData(expectedDataId));
+
+ verify(tested);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/staticmocking/ServiceRegistratorTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/staticmocking/ServiceRegistratorTest.java
new file mode 100644
index 0000000..18260eb
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/staticmocking/ServiceRegistratorTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.staticmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * An example on how to mock the call to a static method.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(IdGenerator.class)
+public class ServiceRegistratorTest {
+
+ @Test
+ public void registersServiceToRepository() throws Exception {
+ long expectedId = 42;
+
+ // We create a new instance of the class under test as usually.
+ ServiceRegistrator tested = new ServiceRegistrator();
+
+ // This is the way to tell PowerMock to mock all static methods of a
+ // given class
+ mockStatic(IdGenerator.class);
+
+ /*
+ * The static method call to IdGenerator.generateNewId() expectation.
+ * This is why we need PowerMock.
+ */
+ expect(IdGenerator.generateNewId()).andReturn(expectedId);
+
+ // Note how we replay the class, not the instance!
+ replay(IdGenerator.class);
+
+ long actualId = tested.registerService(new Object());
+
+ // Note how we verify the class, not the instance!
+ verify(IdGenerator.class);
+
+ // Assert that the ID is correct
+ assertEquals(expectedId, actualId);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructorTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructorTest.java
new file mode 100644
index 0000000..c6eccc4
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilConstructorTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructor;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertNull;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress an objects own
+ * constructor.
+ */
+public class ExampleWithEvilConstructorTest {
+
+ @Test
+ public void testSuppressOwnConstructor() throws Exception {
+ ExampleWithEvilConstructor tested = Whitebox.newInstance(ExampleWithEvilConstructor.class);
+ assertNull(tested.getMessage());
+ }
+
+ @Test(expected = UnsatisfiedLinkError.class)
+ public void testNotSuppressOwnConstructor() throws Exception {
+ final String message = "myMessage";
+ new ExampleWithEvilConstructor(message);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilParentTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilParentTest.java
new file mode 100644
index 0000000..1bf7201
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructor/ExampleWithEvilParentTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress parent
+ * constructors.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExampleWithEvilParent.class)
+public class ExampleWithEvilParentTest {
+
+ @Test
+ public void testSuppressConstructorOfEvilParent() throws Exception {
+ suppress(constructor(EvilParent.class));
+ final String message = "myMessage";
+ ExampleWithEvilParent tested = new ExampleWithEvilParent(message);
+ assertEquals(message, tested.getMessage());
+ }
+
+ @Test(expected = UnsatisfiedLinkError.class)
+ public void testNotSuppressConstructorOfEvilParent() throws Exception {
+ final String message = "myMessage";
+ new ExampleWithEvilParent(message);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParentTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParentTest.java
new file mode 100644
index 0000000..3f2e1c9
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/constructorhierarchy/ExampleWithEvilParentAndEvilGrandParentTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.constructorhierarchy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * Example that demonstrates PowerMock's ability to suppress constructor
+ * hierarchies.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExampleWithEvilParentAndEvilGrandParent.class)
+public class ExampleWithEvilParentAndEvilGrandParentTest {
+
+ @Test
+ public void testSuppressConstructorHierarchy() throws Exception {
+ suppress(constructor(EvilParent.class));
+ final String message = "myMessage";
+ ExampleWithEvilParentAndEvilGrandParent tested = new ExampleWithEvilParentAndEvilGrandParent(message);
+ assertEquals(message, tested.getMessage());
+ }
+
+ @Test
+ public void testSuppressConstructorOfEvilChild() throws Exception {
+ suppress(constructor(EvilParent.class));
+ final String message = "myMessage";
+ new ExampleWithEvilParentAndEvilGrandParent(message);
+ }
+
+ @Test(expected = UnsatisfiedLinkError.class)
+ public void testNotSuppressConstructorOfEvilChild() throws Exception {
+ final String message = "myMessage";
+ new ExampleWithEvilParentAndEvilGrandParent(message);
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/method/ExampleWithEvilMethodTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/method/ExampleWithEvilMethodTest.java
new file mode 100644
index 0000000..50983f6
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/method/ExampleWithEvilMethodTest.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.method;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * This test demonstrates PowerMock's ability to suppress methods.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExampleWithEvilMethod.class)
+public class ExampleWithEvilMethodTest {
+
+ @Test
+ public void testSuppressMethod() throws Exception {
+ suppress(method(ExampleWithEvilMethod.class, "getEvilMessage"));
+ final String message = "myMessage";
+ ExampleWithEvilMethod tested = new ExampleWithEvilMethod(message);
+ assertEquals(message + "null", tested.getMessage());
+ }
+}
diff --git a/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializerTest.java b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializerTest.java
new file mode 100644
index 0000000..7802eaf
--- /dev/null
+++ b/examples/DocumentationExamples/src/test/java/powermock/examples/suppress/staticinitializer/ExampleWithEvilStaticInitializerTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.suppress.staticinitializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test demonstrates the ability for PowerMock to remove static
+ * initializers.
+ */
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("powermock.examples.suppress.staticinitializer.ExampleWithEvilStaticInitializer")
+public class ExampleWithEvilStaticInitializerTest {
+
+ @Test
+ public void testSuppressStaticInitializer() throws Exception {
+ final String message = "myMessage";
+ ExampleWithEvilStaticInitializer tested = new ExampleWithEvilStaticInitializer(message);
+ assertEquals(message, tested.getMessage());
+ }
+}
\ No newline at end of file
diff --git a/examples/HamcrestExample/pom.xml b/examples/HamcrestExample/pom.xml
new file mode 100644
index 0000000..eabd2fa
--- /dev/null
+++ b/examples/HamcrestExample/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-hamcrestexample</artifactId>
+ <name>HamcrestExample</name>
+
+ <description>
+ Examples showing PowerMock used with Hamcrest matchers.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/HamcrestExample/src/main/java/org/powermock/hamcrest/HamcrestExample.java b/examples/HamcrestExample/src/main/java/org/powermock/hamcrest/HamcrestExample.java
new file mode 100644
index 0000000..e4136cc
--- /dev/null
+++ b/examples/HamcrestExample/src/main/java/org/powermock/hamcrest/HamcrestExample.java
@@ -0,0 +1,12 @@
+package org.powermock.hamcrest;
+
+/**
+ * A very simple class that's used just to assert that PowerMock works together
+ * with Hamcrest.
+ */
+public class HamcrestExample {
+
+ public static String getString() {
+ return "hamcrest";
+ }
+}
diff --git a/examples/HamcrestExample/src/test/java/org/powermock/hamcrest/HamcrestExampleTest.java b/examples/HamcrestExample/src/test/java/org/powermock/hamcrest/HamcrestExampleTest.java
new file mode 100644
index 0000000..f6506fa
--- /dev/null
+++ b/examples/HamcrestExample/src/test/java/org/powermock/hamcrest/HamcrestExampleTest.java
@@ -0,0 +1,21 @@
+package org.powermock.hamcrest;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+
+/**
+ * A simple test case that asserts the PowerMock works together with Hamcrest
+ * matchers.
+ */
+ at RunWith(PowerMockRunner.class)
+public class HamcrestExampleTest {
+
+ @Test
+ public void testGetString() throws Exception {
+ assertThat("File extension", HamcrestExample.getString(), is("hamcrest"));
+ }
+}
diff --git a/examples/SignedMocking/pom.xml b/examples/SignedMocking/pom.xml
new file mode 100644
index 0000000..8b0c708
--- /dev/null
+++ b/examples/SignedMocking/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-signedmocking</artifactId>
+ <name>SignedMocking</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ Examples showing PowerMock used to mock classes in signed jars.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.acegisecurity</groupId>
+ <artifactId>acegi-security</artifactId>
+ <version>1.0.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-dao</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-remoting</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-support</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>oro</groupId>
+ <artifactId>oro</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/SignedMocking/src/main/java/org/powermock/examples/AcegiSecurityUser.java b/examples/SignedMocking/src/main/java/org/powermock/examples/AcegiSecurityUser.java
new file mode 100644
index 0000000..d9f7d5b
--- /dev/null
+++ b/examples/SignedMocking/src/main/java/org/powermock/examples/AcegiSecurityUser.java
@@ -0,0 +1,22 @@
+package org.powermock.examples;
+
+import org.acegisecurity.acl.basic.BasicAclEntry;
+import org.acegisecurity.acl.basic.cache.NullAclEntryCache;
+
+/**
+ * A simple naive example of a class that uses a dependency in the Acegi
+ * Security framework (which is signed). Using plain EasyMock you'd would not be
+ * able to mock a class located in the Acegi Security jar file.
+ */
+public class AcegiSecurityUser {
+
+ private NullAclEntryCache cache;
+
+ public AcegiSecurityUser(NullAclEntryCache cache) {
+ this.cache = cache;
+ }
+
+ public BasicAclEntry[] getDecisionVoters() {
+ return cache.getEntriesFromCache(null);
+ }
+}
diff --git a/examples/SignedMocking/src/test/java/org/powermock/examples/AcegiSecurityUserTest.java b/examples/SignedMocking/src/test/java/org/powermock/examples/AcegiSecurityUserTest.java
new file mode 100644
index 0000000..c9fda21
--- /dev/null
+++ b/examples/SignedMocking/src/test/java/org/powermock/examples/AcegiSecurityUserTest.java
@@ -0,0 +1,36 @@
+package org.powermock.examples;
+
+import org.acegisecurity.acl.basic.BasicAclEntry;
+import org.acegisecurity.acl.basic.cache.NullAclEntryCache;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertSame;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit tests that demonstrates PowerMock's ability to mock classes in signed
+ * jars.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(NullAclEntryCache.class)
+public class AcegiSecurityUserTest {
+
+ @Test
+ public void testMockSigned() throws Exception {
+ NullAclEntryCache cacheMock = createMock(NullAclEntryCache.class);
+ AcegiSecurityUser tested = new AcegiSecurityUser(cacheMock);
+
+ final BasicAclEntry[] basicAclEntries = new BasicAclEntry[0];
+ expect(cacheMock.getEntriesFromCache(null)).andReturn(basicAclEntries);
+
+ replay(cacheMock);
+
+ assertSame(basicAclEntries, tested.getDecisionVoters());
+
+ verify(cacheMock);
+ }
+}
diff --git a/examples/byte-buddy-easymock/pom.xml b/examples/byte-buddy-easymock/pom.xml
new file mode 100644
index 0000000..02b68ef
--- /dev/null
+++ b/examples/byte-buddy-easymock/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-byte-buddy-easymock</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Example demonstrating that PowerMock EasyMock API and Byte Buddy works together.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ <version>0.6.15</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/byte-buddy-easymock/src/main/java/powermock/examples/bytebuddy/easymock/SampleClass.java b/examples/byte-buddy-easymock/src/main/java/powermock/examples/bytebuddy/easymock/SampleClass.java
new file mode 100644
index 0000000..2471385
--- /dev/null
+++ b/examples/byte-buddy-easymock/src/main/java/powermock/examples/bytebuddy/easymock/SampleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.bytebuddy.easymock;
+
+public class SampleClass {
+}
\ No newline at end of file
diff --git a/examples/byte-buddy-easymock/src/test/java/powermock/examples/bytebuddy/easymock/ByteBuddyWithPowerMockTest.java b/examples/byte-buddy-easymock/src/test/java/powermock/examples/bytebuddy/easymock/ByteBuddyWithPowerMockTest.java
new file mode 100644
index 0000000..86858f3
--- /dev/null
+++ b/examples/byte-buddy-easymock/src/test/java/powermock/examples/bytebuddy/easymock/ByteBuddyWithPowerMockTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.bytebuddy;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import org.junit.After;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.bytebuddy.easymock.SampleClass;
+
+import java.util.Map;
+
+import static org.easymock.EasyMock.createMock;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SampleClass.class)
+public class ByteBuddyWithPowerMockTest {
+
+ @Test
+ @Ignore("Unfortunately this doesn't work")
+ public void assertThatPowerMockAndByteBuddyWorksTogetherWhenCallingMockFromEasyMock() throws Exception {
+ SampleClass sample = createMock(SampleClass.class);
+ assertThat(proxy(sample).getClass().getName(), containsString("$ByteBuddy$"));
+ }
+
+ @Test
+ public void assertThatPowerMockAndByteBuddyWorksTogetherWhenCallingMockFromPowerMock() throws Exception {
+ SampleClass sample = PowerMock.createMock(SampleClass.class);
+ assertThat(proxy(sample).getClass().getName(), containsString("$ByteBuddy$"));
+ }
+
+ @After public void
+ clearPowerMockClassCacheAfterEachTest() {
+ MockClassLoader mcl = (MockClassLoader) SampleClass.class.getClassLoader();
+ Whitebox.getInternalState(mcl, Map.class).clear();
+ }
+
+ private static SampleClass proxy(SampleClass sample)
+ throws IllegalAccessException, InstantiationException {
+ return new ByteBuddy()
+ .subclass(sample.getClass())
+ .make()
+ .load(sample.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded().newInstance();
+ }
+}
\ No newline at end of file
diff --git a/examples/byte-buddy-mockito/pom.xml b/examples/byte-buddy-mockito/pom.xml
new file mode 100644
index 0000000..bd1fb07
--- /dev/null
+++ b/examples/byte-buddy-mockito/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-byte-buddy-mockito</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Example demonstrating that PowerMock and Byte Buddy works together.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>net.bytebuddy</groupId>
+ <artifactId>byte-buddy</artifactId>
+ <version>0.6.15</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/byte-buddy-mockito/src/main/java/powermock/examples/bytebuddy/mockito/SampleClass.java b/examples/byte-buddy-mockito/src/main/java/powermock/examples/bytebuddy/mockito/SampleClass.java
new file mode 100644
index 0000000..945e9d2
--- /dev/null
+++ b/examples/byte-buddy-mockito/src/main/java/powermock/examples/bytebuddy/mockito/SampleClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.bytebuddy.mockito;
+
+public class SampleClass {
+}
\ No newline at end of file
diff --git a/examples/byte-buddy-mockito/src/test/java/powermock/examples/bytebuddy/mockito/ByteBuddyWithPowerMockitoTest.java b/examples/byte-buddy-mockito/src/test/java/powermock/examples/bytebuddy/mockito/ByteBuddyWithPowerMockitoTest.java
new file mode 100644
index 0000000..99082c2
--- /dev/null
+++ b/examples/byte-buddy-mockito/src/test/java/powermock/examples/bytebuddy/mockito/ByteBuddyWithPowerMockitoTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.bytebuddy.mockito;
+
+import net.bytebuddy.ByteBuddy;
+import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import powermock.examples.bytebuddy.mockito.SampleClass;
+
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SampleClass.class)
+public class ByteBuddyWithPowerMockitoTest {
+
+ @Mock
+ private SampleClass sample;
+
+ @Test
+ public void assertThatPowerMockAndByteBuddyWorksTogetherWhenCallingMockFromMockito() throws Exception {
+ SampleClass sample = mock(SampleClass.class);
+ assertThat(proxy(sample).getClass().getName(), containsString("$ByteBuddy$"));
+ }
+
+ @Test
+ public void assertThatPowerMockAndByteBuddyWorksTogetherWhenCallingMockFromPowerMockito() throws Exception {
+ SampleClass sample = PowerMockito.mock(SampleClass.class);
+ assertThat(proxy(sample).getClass().getName(), containsString("$ByteBuddy$"));
+ }
+
+ @Test
+ public void assertThatPowerMockAndByteBuddyWorksTogetherWhenMockIsInjected() throws Exception {
+ assertThat(proxy(sample).getClass().getName(), containsString("$ByteBuddy$"));
+ }
+
+ @After public void
+ clearPowerMockClassCacheAfterEachTest() {
+ MockClassLoader mcl = (MockClassLoader) SampleClass.class.getClassLoader();
+ Whitebox.getInternalState(mcl, Map.class).clear();
+ }
+
+ private static SampleClass proxy(SampleClass sample)
+ throws IllegalAccessException, InstantiationException {
+ return new ByteBuddy()
+ .subclass(sample.getClass())
+ .make()
+ .load(sample.getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER)
+ .getLoaded().newInstance();
+ }
+}
\ No newline at end of file
diff --git a/examples/dom4j/pom.xml b/examples/dom4j/pom.xml
new file mode 100644
index 0000000..0ccf504
--- /dev/null
+++ b/examples/dom4j/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-dom4j</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Example showing how to suppress static initializers.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>1.6.1</version>
+ </dependency>
+ <dependency>
+ <groupId>jaxen</groupId>
+ <artifactId>jaxen</artifactId>
+ <version>1.1-beta-6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/dom4j/src/main/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBase.java b/examples/dom4j/src/main/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBase.java
new file mode 100644
index 0000000..4c5b32b
--- /dev/null
+++ b/examples/dom4j/src/main/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBase.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.examples.dom4j;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.dom4j.io.XMLWriter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Random;
+
+/**
+ * A base class that may be inherited by request creators that implement
+ * {@link IRequestCreator} to create xml requests (that should be parsed to
+ * byte[] data).
+ */
+public abstract class AbstractXMLRequestCreatorBase {
+
+ /**
+ * Convert a dom4j xml document to a byte[].
+ *
+ * @param document
+ * The document to convert.
+ * @return A <code>byte[]</code> representation of the xml document.
+ * @throws IOException
+ * If an exception occurs when converting the document.
+ */
+ public byte[] convertDocumentToByteArray(Document document)
+ throws IOException {
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ XMLWriter writer = new XMLWriter(stream);
+ byte[] documentAsByteArray = null;
+ try {
+ writer.write(document);
+ } finally {
+ writer.close();
+ stream.flush();
+ stream.close();
+ }
+ documentAsByteArray = stream.toByteArray();
+ return documentAsByteArray;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public final byte[] createRequest(String... params) {
+ Document document = DocumentHelper.createDocument();
+ Element root = document.addElement(XMLProtocol.ENCODE_ELEMENT);
+ Element header = root.addElement(XMLProtocol.HEADER_ELEMENT);
+ header.addAttribute(XMLProtocol.HEADER_MSG_ID_ATTRIBUTE,
+ generateRandomId());
+ Element body = root.addElement(XMLProtocol.BODY_ELEMENT);
+ createBody(body, params);
+ byte[] array = null;
+ try {
+ array = convertDocumentToByteArray(document);
+ } catch (IOException e) {
+ throw new RuntimeException("Failed to create request", e);
+ }
+ return array;
+ }
+
+ /**
+ * Subclasses should implement this method to add the body content of the
+ * request.
+ *
+ * @param body
+ * The message body. Subclasses should append new elements to
+ * this body.
+ *
+ * @param parameters
+ * Parameters that may be used when creating the request, for
+ * example the ID of the request. May be <code>null</code> if
+ * that's appropriate for a specific request creator.
+ */
+ protected abstract void createBody(Element body, String... parameters);
+
+ /**
+ * Generates a random <code>int</code> between 0 and 999. This
+ * <code>int</code> is then converted to a String which is returned.
+ *
+ * @return A new String of the generated <code>int</code>.
+ */
+ String generateRandomId() {
+ return Integer.toString(new Random(System.nanoTime()).nextInt(1000));
+ }
+}
diff --git a/examples/dom4j/src/main/java/org/powermock/examples/dom4j/XMLProtocol.java b/examples/dom4j/src/main/java/org/powermock/examples/dom4j/XMLProtocol.java
new file mode 100644
index 0000000..7de9d30
--- /dev/null
+++ b/examples/dom4j/src/main/java/org/powermock/examples/dom4j/XMLProtocol.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.examples.dom4j;
+
+public final class XMLProtocol {
+
+ private XMLProtocol() {
+ }
+
+ public static final String ENCODE_ELEMENT = "EncodeElement";
+
+ public static final String HEADER_ELEMENT = "MyHeader";
+
+ public static final String HEADER_MSG_ID_ATTRIBUTE = "MyMsgIdAttribute";
+
+ public static final String BODY_ELEMENT = "BodyElement";
+
+}
diff --git a/examples/dom4j/src/test/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBaseTest.java b/examples/dom4j/src/test/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBaseTest.java
new file mode 100644
index 0000000..3c3b7fa
--- /dev/null
+++ b/examples/dom4j/src/test/java/org/powermock/examples/dom4j/AbstractXMLRequestCreatorBaseTest.java
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.examples.dom4j;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit test for the {@link AbstractXMLRequestCreatorBase} class.
+ */
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("org.dom4j.tree.AbstractNode")
+ at PrepareForTest( { DocumentHelper.class })
+public class AbstractXMLRequestCreatorBaseTest {
+ private AbstractXMLRequestCreatorBase tested;
+
+ private Document documentMock;
+
+ private Element rootElementMock;
+
+ private Element headerElementMock;
+
+ private Element bodyElementMock;
+
+ @Before
+ public void setUp() throws Exception {
+ tested = new AbstractXMLRequestCreatorBase() {
+ @Override
+ protected void createBody(Element body, String... parameters) {
+
+ }
+ };
+ PowerMock.niceReplayAndVerify();
+ documentMock = createMock(Document.class);
+ rootElementMock = createMock(Element.class);
+ headerElementMock = createMock(Element.class);
+ bodyElementMock = createMock(Element.class);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ tested = null;
+ documentMock = null;
+ rootElementMock = null;
+ headerElementMock = null;
+ bodyElementMock = null;
+ }
+
+ /**
+ * Replay all mocks
+ */
+ protected void replayAll() {
+ replay(tested, documentMock, rootElementMock, headerElementMock, bodyElementMock);
+ }
+
+ /**
+ * Verify all mocks
+ */
+ protected void verifyAll() {
+ verify(tested, documentMock, rootElementMock, headerElementMock, bodyElementMock);
+ }
+
+ /**
+ * Test convert document to byte array.
+ *
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ @Test
+ @PrepareForTest
+ @SuppressStaticInitializationFor
+ public void testConvertDocumentToByteArray() throws Exception {
+ // Create a fake document.
+ Document document = DocumentHelper.createDocument();
+ Element root = document.addElement("ListExecutionContexts");
+ root.addAttribute("id", "2");
+ replayAll();
+ // Perform the test
+ final byte[] array = tested.convertDocumentToByteArray(document);
+ verifyAll();
+ assertNotNull(array);
+ assertEquals(70, array.length);
+ }
+
+ /**
+ * Happy-flow test for the
+ * {@link AbstractXMLRequestCreatorBase#createRequest(String[])} method.
+ *
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ @Test
+ public void testCreateRequest() throws Exception {
+ tested = createPartialMock(AbstractXMLRequestCreatorBase.class, "convertDocumentToByteArray", "createBody", "generateRandomId");
+ mockStatic(DocumentHelper.class);
+ // Expectations
+ final String[] params = new String[] { "String1", "String2" };
+ final byte[] expected = new byte[] { 42 };
+
+ expect(DocumentHelper.createDocument()).andReturn(documentMock);
+ expect(documentMock.addElement(XMLProtocol.ENCODE_ELEMENT)).andReturn(rootElementMock);
+ expect(rootElementMock.addElement(XMLProtocol.HEADER_ELEMENT)).andReturn(headerElementMock);
+ final String id = "213";
+ expect(tested.generateRandomId()).andReturn(id);
+ expect(headerElementMock.addAttribute(XMLProtocol.HEADER_MSG_ID_ATTRIBUTE, id)).andReturn(null);
+ expect(rootElementMock.addElement(XMLProtocol.BODY_ELEMENT)).andReturn(bodyElementMock);
+ tested.createBody(bodyElementMock, params);
+ expectLastCall().times(1);
+ expect(tested.convertDocumentToByteArray(documentMock)).andReturn(expected);
+
+ replayAll();
+ replay(DocumentHelper.class);
+
+ byte[] actual = tested.createRequest(params);
+
+ verifyAll();
+ verify(DocumentHelper.class);
+
+ assertArrayEquals(expected, actual);
+ }
+}
diff --git a/examples/easymock31/pom.xml b/examples/easymock31/pom.xml
new file mode 100644
index 0000000..065fc13
--- /dev/null
+++ b/examples/easymock31/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-easymock31</artifactId>
+ <name>Simple Demo how to use PowerMock with EasyMock 3.1</name>
+
+ <description>
+ Example demonstrating that PowerMock supports EasyMock 3.1
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Greeter.java b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Greeter.java
new file mode 100644
index 0000000..e276fc2
--- /dev/null
+++ b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Greeter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.easymock31;
+
+
+/**
+ * Hello world!
+ *
+ */
+public class Greeter {
+ public static void main( String[] args ) {
+ new Greeter().run(5, getMessage());
+ }
+
+ private void run(int count, String message) {
+ Logger logger = new Logger();
+ for(int indx=0; indx<count; indx++){
+ logger.log(message);
+ }
+ }
+
+ private static String getMessage() {
+ return SimpleConfig.getGreeting() + " " + SimpleConfig.getTarget();
+ }
+}
diff --git a/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Logger.java b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Logger.java
new file mode 100644
index 0000000..7649dee
--- /dev/null
+++ b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/Logger.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.easymock31;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class Logger {
+ private PrintWriter writer;
+
+ public Logger() {
+ try {
+ writer = new PrintWriter(new FileWriter("target/logger.log"));
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void log(String message) {
+ writer.println(message);
+ }
+}
diff --git a/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/SimpleConfig.java b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/SimpleConfig.java
new file mode 100644
index 0000000..ba000d3
--- /dev/null
+++ b/examples/easymock31/src/main/java/demo/org/powermock/examples/easymock31/SimpleConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.easymock31;
+
+import java.util.Properties;
+
+public class SimpleConfig {
+
+ private static Properties PROPERTIES = new Properties();
+
+ static {
+ try {
+ PROPERTIES.load(SimpleConfig.class.getClassLoader().getResourceAsStream("simpleConfig.properties"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String getGreeting() {
+ return PROPERTIES.getProperty("greeting");
+ }
+
+ public static String getTarget() {
+ return PROPERTIES.getProperty("target");
+ }
+}
diff --git a/examples/easymock31/src/test/java/demo/org/powermock/examples/easymock31/GreeterTest.java b/examples/easymock31/src/test/java/demo/org/powermock/examples/easymock31/GreeterTest.java
new file mode 100644
index 0000000..792627a
--- /dev/null
+++ b/examples/easymock31/src/test/java/demo/org/powermock/examples/easymock31/GreeterTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.easymock31;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static junit.framework.Assert.assertEquals;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.reflect.Whitebox.invokeMethod;
+
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("demo.org.powermock.examples.easymock31.SimpleConfig")
+ at PrepareForTest( { Greeter.class, Logger.class })
+public class GreeterTest {
+
+ @Test
+ public void testGetMessage() throws Exception {
+ mockStatic(SimpleConfig.class);
+ expect(SimpleConfig.getGreeting()).andReturn("Hi");
+ expect(SimpleConfig.getTarget()).andReturn("All");
+ replay(SimpleConfig.class);
+
+ assertEquals("Hi All", invokeMethod(Greeter.class, "getMessage"));
+
+ verify(SimpleConfig.class);
+ }
+
+
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRunWhenLoggerThrowsUnexpectedRuntimeException() throws Exception {
+ expectNew(Logger.class).andThrow(new IllegalArgumentException("Unexpected exeception"));
+ replay(Logger.class);
+
+ invokeMethod(new Greeter(), "run", 10, "Hello");
+
+ verify(Logger.class);
+ }
+
+ /**
+ * This test demonstrates that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=110">issue
+ * 110</a> has been resolved.
+ */
+ @Test
+ @PrepareForTest( { SimpleConfig.class })
+ public void assertItsOkToInvokeReflectionMethodsOnClasses() throws Exception {
+ new SimpleConfig();
+ }
+}
\ No newline at end of file
diff --git a/examples/java8/pom.xml b/examples/java8/pom.xml
new file mode 100644
index 0000000..f2dad6e
--- /dev/null
+++ b/examples/java8/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2014 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-java8</artifactId>
+ <name>java8</name>
+
+ <description>
+ Example of using Java 8.
+ </description>
+
+ <profiles>
+ <profile>
+ <id>mockito</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ <profile>
+ <id>mockito2</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.2</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/examples/java8/src/main/java/demo/org/powermock/examples/SimpleOps.java b/examples/java8/src/main/java/demo/org/powermock/examples/SimpleOps.java
new file mode 100644
index 0000000..f141690
--- /dev/null
+++ b/examples/java8/src/main/java/demo/org/powermock/examples/SimpleOps.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class SimpleOps {
+ public List<String> doStreamStuff(List<String> inputs) {
+ return inputs.stream().collect(Collectors.toList());
+ }
+}
diff --git a/examples/java8/src/test/java/demo/org/powermock/examples/SimpleOpsTest.java b/examples/java8/src/test/java/demo/org/powermock/examples/SimpleOpsTest.java
new file mode 100644
index 0000000..ba21cb2
--- /dev/null
+++ b/examples/java8/src/test/java/demo/org/powermock/examples/SimpleOpsTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package demo.org.powermock.examples;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.Collections;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleOps.class)
+public class SimpleOpsTest {
+
+ /**
+ * Asserts that <a href="https://code.google.com/p/powermock/issues/detail?id=513">issue 513</a> is resolved.
+ */
+ @Test public void
+ can_call_methods_using_default_methods() {
+ SimpleOps ops = new SimpleOps();
+ ops.doStreamStuff(Collections.emptyList());
+ }
+}
diff --git a/examples/jcl/pom.xml b/examples/jcl/pom.xml
new file mode 100644
index 0000000..de083e1
--- /dev/null
+++ b/examples/jcl/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-jcl</artifactId>
+ <name>jcl</name>
+
+ <description>
+ Example of using JclMockPolicy.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.15</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.jmx</groupId>
+ <artifactId>jmxri</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.jdmk</groupId>
+ <artifactId>jmxtools</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.jms</groupId>
+ <artifactId>jms</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/jcl/src/main/java/org/powermock/examples/JclUser.java b/examples/jcl/src/main/java/org/powermock/examples/JclUser.java
new file mode 100644
index 0000000..1b448cd
--- /dev/null
+++ b/examples/jcl/src/main/java/org/powermock/examples/JclUser.java
@@ -0,0 +1,13 @@
+package org.powermock.examples;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class JclUser {
+ private static final Log log = LogFactory.getLog(JclUser.class);
+
+ public final String getMessage() {
+ log.debug("getMessage!");
+ return "log4j user";
+ }
+}
\ No newline at end of file
diff --git a/examples/jcl/src/test/java/org/powermock/examples/JclUserTest.java b/examples/jcl/src/test/java/org/powermock/examples/JclUserTest.java
new file mode 100644
index 0000000..cb24bcb
--- /dev/null
+++ b/examples/jcl/src/test/java/org/powermock/examples/JclUserTest.java
@@ -0,0 +1,36 @@
+package org.powermock.examples;
+
+import org.apache.commons.logging.Log;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.mockpolicies.JclMockPolicy;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Proxy;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Unit tests that assert that the {@link JclMockPolicy} works.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(JclMockPolicy.class)
+public class JclUserTest {
+
+ @Test
+ public void assertJclMockPolicyWorks() throws Exception {
+ final JclUser tested = new JclUser();
+
+ assertTrue(Proxy.isProxyClass(Whitebox.getInternalState(JclUser.class, Log.class).getClass()));
+
+ replayAll();
+
+ tested.getMessage();
+
+ verifyAll();
+ }
+}
diff --git a/examples/jdom/pom.xml b/examples/jdom/pom.xml
new file mode 100644
index 0000000..db55e69
--- /dev/null
+++ b/examples/jdom/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-jdom</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Example showing PowerMock used with jDom and static classes.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jdom</groupId>
+ <artifactId>jdom</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/jdom/src/main/java/examples/jdom/StaticClass.java b/examples/jdom/src/main/java/examples/jdom/StaticClass.java
new file mode 100644
index 0000000..f08a41a
--- /dev/null
+++ b/examples/jdom/src/main/java/examples/jdom/StaticClass.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package examples.jdom;
+
+
+public class StaticClass {
+ static int staticMethod() {
+ return 1;
+ }
+}
diff --git a/examples/jdom/src/test/java/examples/jdom/StaticWithJdomTest.java b/examples/jdom/src/test/java/examples/jdom/StaticWithJdomTest.java
new file mode 100644
index 0000000..dec4cd1
--- /dev/null
+++ b/examples/jdom/src/test/java/examples/jdom/StaticWithJdomTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package examples.jdom;
+
+import org.easymock.EasyMock;
+import org.jdom.Document;
+import org.jdom.input.SAXBuilder;
+import org.junit.Assert;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.io.StringReader;
+
+/**
+ * Thanks to Manuel Fern�ndez S�nchez de la Blanca for this example.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticClass.class })
+ at PowerMockIgnore( { "org.jdom.*", "com.sun.org.apache.xerces.*" })
+public class StaticWithJdomTest {
+
+ @org.junit.Test
+ public void test() throws Exception {
+
+ PowerMock.mockStatic(StaticClass.class);
+ EasyMock.expect(StaticClass.staticMethod()).andReturn(2).anyTimes();
+ PowerMock.replay(StaticClass.class);
+
+ int i = StaticClass.staticMethod();
+
+ String xml = "<xml>" + i + "</xml>";
+ SAXBuilder b = new SAXBuilder();
+
+ Document d = b.build(new StringReader(xml));
+ Assert.assertTrue(d.getRootElement().getText().equals("2"));
+ PowerMock.verify(StaticClass.class);
+ }
+}
diff --git a/examples/jmock/pom.xml b/examples/jmock/pom.xml
new file mode 100644
index 0000000..d13905d
--- /dev/null
+++ b/examples/jmock/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-jmock</artifactId>
+ <name>JMock Example</name>
+ <properties>
+ <jmock.version>2.5.1</jmock.version>
+ </properties>
+
+ <description>
+ Examples showing PowerMock with JMock
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock-junit4</artifactId>
+ <version>${jmock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jmock</groupId>
+ <artifactId>jmock-legacy</artifactId>
+ <version>${jmock.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <!--
+ We depend on the EasyMock API but exclude the EasyMock dependency. The reason
+ is that PowerMock Whitebox needs a "org.powermock.reflect.spi.ProxyFramework"
+ implementation in order to work correctly. This implementation is provided by
+ the extension API:s. Since JMock uses CGLib it can reuse the
+ "org.powermock.api.extension.proxyframework.ProxyFrameworkImpl" in the
+ PowerMock EasyMock API. An alternative to depend on this class would be to simply copy
+ the class it into your code (remember that the class must be named
+ org.powermock.api.extension.proxyframework.ProxyFrameworkImpl).
+ -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/jmock/src/main/java/powermock/examples/jmock/ClassWithStaticMethod.java b/examples/jmock/src/main/java/powermock/examples/jmock/ClassWithStaticMethod.java
new file mode 100644
index 0000000..336052b
--- /dev/null
+++ b/examples/jmock/src/main/java/powermock/examples/jmock/ClassWithStaticMethod.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.jmock;
+
+/**
+ * Class with static methods
+ */
+public class ClassWithStaticMethod {
+
+ public static String returnString() {
+ return "a string";
+ }
+}
diff --git a/examples/jmock/src/main/java/powermock/examples/jmock/FinalClass.java b/examples/jmock/src/main/java/powermock/examples/jmock/FinalClass.java
new file mode 100644
index 0000000..aff50dd
--- /dev/null
+++ b/examples/jmock/src/main/java/powermock/examples/jmock/FinalClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.jmock;
+
+/**
+ * Example of a final class
+ */
+public final class FinalClass {
+
+ public String helloWorld() {
+ return "Hello world";
+ }
+}
diff --git a/examples/jmock/src/main/java/powermock/examples/jmock/JMockExample.java b/examples/jmock/src/main/java/powermock/examples/jmock/JMockExample.java
new file mode 100644
index 0000000..6534491
--- /dev/null
+++ b/examples/jmock/src/main/java/powermock/examples/jmock/JMockExample.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.jmock;
+
+/**
+ * Simple class that uses a static method and a final class.
+ */
+public class JMockExample {
+ private final FinalClass finalClass;
+
+ public JMockExample(FinalClass finalClass) {
+ this.finalClass = finalClass;
+ }
+
+ public String generateMessage() {
+ return "Message is: "+ finalClass.helloWorld() + ClassWithStaticMethod.returnString();
+ }
+}
diff --git a/examples/jmock/src/test/java/powermock/examples/jmock/JMockFinalClassTest.java b/examples/jmock/src/test/java/powermock/examples/jmock/JMockFinalClassTest.java
new file mode 100644
index 0000000..298647c
--- /dev/null
+++ b/examples/jmock/src/test/java/powermock/examples/jmock/JMockFinalClassTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.jmock;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Demonstrates how to use PowerMock with unsupported frameworks like JMock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalClass.class)
+public class JMockFinalClassTest {
+ private Mockery context = new JUnit4Mockery(){{
+ setImposteriser(ClassImposteriser.INSTANCE);
+ }};
+
+ private FinalClass tested;
+
+ @Before
+ public void setup() throws Exception {
+ tested = context.mock(FinalClass.class);
+ }
+
+ @Test
+ public void mockFinalClassWithPowerMockAndJMock() throws Exception {
+ // Given
+ final String expected = "something";
+ context.checking(new Expectations(){{
+ one(tested).helloWorld();
+ will(returnValue(expected));
+ }});
+
+ // When
+ final String actual = tested.helloWorld();
+ assertEquals(expected, actual);
+
+ // Then
+ context.assertIsSatisfied();
+ }
+}
diff --git a/examples/jmock/src/test/java/powermock/examples/jmock/JMockStaticMethodTest.java b/examples/jmock/src/test/java/powermock/examples/jmock/JMockStaticMethodTest.java
new file mode 100644
index 0000000..f81d698
--- /dev/null
+++ b/examples/jmock/src/test/java/powermock/examples/jmock/JMockStaticMethodTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.jmock;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+/**
+ * Demonstrates how to use PowerMock with unsupported frameworks like JMock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({FinalClass.class, ClassWithStaticMethod.class})
+public class JMockStaticMethodTest {
+ private Mockery context = new JUnit4Mockery(){{
+ setImposteriser(ClassImposteriser.INSTANCE);
+ }};
+
+ private FinalClass finalClassMock;
+ private JMockExample tested;
+
+ @Before
+ public void setup() throws Exception {
+ finalClassMock = context.mock(FinalClass.class);
+ tested = new JMockExample(finalClassMock);
+ }
+
+ @Test
+ public void mockFinalClassWithPowerMockAndJMock() throws Exception {
+ // Given
+ context.checking(new Expectations(){{
+ one(finalClassMock).helloWorld();
+ will(returnValue("Hello "));
+ }});
+
+ // Stub the static method
+ stub(method(ClassWithStaticMethod.class, "returnString")).toReturn("JMock");
+
+ // When
+ final String message = tested.generateMessage();
+ assertEquals("Message is: Hello JMock", message);
+
+ // Then
+ context.assertIsSatisfied();
+ }
+}
diff --git a/examples/log4j/pom.xml b/examples/log4j/pom.xml
new file mode 100644
index 0000000..2cba0e8
--- /dev/null
+++ b/examples/log4j/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-log4j</artifactId>
+ <name>log4j</name>
+
+ <description>
+ Example of using Log4jMockPolicy.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.15</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.jmx</groupId>
+ <artifactId>jmxri</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>com.sun.jdmk</groupId>
+ <artifactId>jmxtools</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.jms</groupId>
+ <artifactId>jms</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUser.java b/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUser.java
new file mode 100644
index 0000000..1864e91
--- /dev/null
+++ b/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUser.java
@@ -0,0 +1,15 @@
+package demo.org.powermock.examples;
+
+
+public class Log4jUser extends Log4jUserParent{
+
+ public final String getMessage() {
+ log.debug("getMessage!");
+ return "log4j user";
+ }
+
+ public String mergeMessageWith(String otherMessage) {
+ log.debug("mergeMessageWith!");
+ return getMessage() + otherMessage;
+ }
+}
diff --git a/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUserParent.java b/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUserParent.java
new file mode 100644
index 0000000..b13085a
--- /dev/null
+++ b/examples/log4j/src/main/java/demo/org/powermock/examples/Log4jUserParent.java
@@ -0,0 +1,7 @@
+package demo.org.powermock.examples;
+
+import org.apache.log4j.Logger;
+
+public class Log4jUserParent {
+ protected static final Logger log = Logger.getLogger(Log4jUserParent.class);
+}
diff --git a/examples/log4j/src/test/java/demo/org/powermock/examples/Log4jUserTest.java b/examples/log4j/src/test/java/demo/org/powermock/examples/Log4jUserTest.java
new file mode 100644
index 0000000..e00a62a
--- /dev/null
+++ b/examples/log4j/src/test/java/demo/org/powermock/examples/Log4jUserTest.java
@@ -0,0 +1,40 @@
+package demo.org.powermock.examples;
+
+import org.apache.log4j.Logger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.mockpolicies.Log4jMockPolicy;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.classloader.annotations.PrepareOnlyThisForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareOnlyThisForTest(Log4jUser.class)
+ at MockPolicy(Log4jMockPolicy.class)
+public class Log4jUserTest {
+
+ @Test
+ public void assertThatLog4jMockPolicyWorks() throws Exception {
+ final Log4jUser tested = createPartialMockAndInvokeDefaultConstructor(Log4jUser.class, "getMessage");
+ final String otherMessage = "other message";
+ final String firstMessage = "first message and ";
+
+ expect(tested.getMessage()).andReturn(firstMessage);
+
+ replayAll();
+
+ final String actual = tested.mergeMessageWith(otherMessage);
+ Class<? extends Logger> class1 = Whitebox.getInternalState(Log4jUserParent.class, Logger.class).getClass();
+ assertTrue(class1.getName().contains("org.apache.log4j.Logger$$EnhancerByCGLIB$$"));
+
+ verifyAll();
+
+ assertEquals(firstMessage + otherMessage, actual);
+ }
+}
diff --git a/examples/pom.xml b/examples/pom.xml
new file mode 100644
index 0000000..af71d97
--- /dev/null
+++ b/examples/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Examples of specific uses of PowerMock.
+ </description>
+
+ <modules>
+ <module>easymock31</module>
+ <module>dom4j</module>
+ <module>simple</module>
+ <module>AbstractFactory</module>
+ <module>tutorial</module>
+ <module>DocumentationExamples</module>
+ <module>SignedMocking</module>
+ <module>HamcrestExample</module>
+ <module>ApacheCLIExample</module>
+ <module>ApacheMina</module>
+ <module>log4j</module>
+ <module>slf4j</module>
+ <module>slf4j-mockito</module>
+ <module>slf4j-noimpl</module>
+ <module>jcl</module>
+ <module>jdom</module>
+ <module>jmock</module>
+ <module>spring-easymock</module>
+ <module>spring-mockito</module>
+ <module>spring-mockito-delegate</module>
+ <module>spring-mockito-xml-agent</module>
+ <module>spring-mockito-xml</module>
+ <module>java8</module>
+ <module>byte-buddy-mockito</module>
+ <module>byte-buddy-easymock</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/examples/simple/pom.xml b/examples/simple/pom.xml
new file mode 100644
index 0000000..60e7f06
--- /dev/null
+++ b/examples/simple/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-simple</artifactId>
+ <name>Simple Demo how to use PowerMock</name>
+
+ <description>
+ Example showing simple PowerMock usage.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/simple/src/main/java/demo/org/powermock/examples/simple/Greeter.java b/examples/simple/src/main/java/demo/org/powermock/examples/simple/Greeter.java
new file mode 100644
index 0000000..9d46009
--- /dev/null
+++ b/examples/simple/src/main/java/demo/org/powermock/examples/simple/Greeter.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.simple;
+
+
+/**
+ * Hello world!
+ *
+ */
+public class Greeter {
+ public static void main( String[] args ) {
+ new Greeter().run(5, getMessage());
+ }
+
+ private void run(int count, String message) {
+ Logger logger = new Logger();
+ for(int indx=0; indx<count; indx++){
+ logger.log(message);
+ }
+ }
+
+ private static String getMessage() {
+ return SimpleConfig.getGreeting() + " " + SimpleConfig.getTarget();
+ }
+}
diff --git a/examples/simple/src/main/java/demo/org/powermock/examples/simple/Logger.java b/examples/simple/src/main/java/demo/org/powermock/examples/simple/Logger.java
new file mode 100644
index 0000000..5a00aec
--- /dev/null
+++ b/examples/simple/src/main/java/demo/org/powermock/examples/simple/Logger.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.simple;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class Logger {
+ private PrintWriter writer;
+
+ public Logger() {
+ try {
+ writer = new PrintWriter(new FileWriter("target/logger.log"));
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ public void log(String message) {
+ writer.println(message);
+ }
+}
diff --git a/examples/simple/src/main/java/demo/org/powermock/examples/simple/SimpleConfig.java b/examples/simple/src/main/java/demo/org/powermock/examples/simple/SimpleConfig.java
new file mode 100644
index 0000000..1262996
--- /dev/null
+++ b/examples/simple/src/main/java/demo/org/powermock/examples/simple/SimpleConfig.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.simple;
+
+import java.util.Properties;
+
+public class SimpleConfig {
+
+ private static Properties PROPERTIES = new Properties();
+
+ static {
+ try {
+ PROPERTIES.load(SimpleConfig.class.getClassLoader().getResourceAsStream("simpleConfig.properties"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static String getGreeting() {
+ return PROPERTIES.getProperty("greeting");
+ }
+
+ public static String getTarget() {
+ return PROPERTIES.getProperty("target");
+ }
+}
diff --git a/examples/simple/src/main/java/simpleConfig.properties b/examples/simple/src/main/java/simpleConfig.properties
new file mode 100644
index 0000000..eabf32c
--- /dev/null
+++ b/examples/simple/src/main/java/simpleConfig.properties
@@ -0,0 +1,2 @@
+greeting=Hello
+target=World
\ No newline at end of file
diff --git a/examples/simple/src/test/java/demo/org/powermock/examples/simple/GreeterTest.java b/examples/simple/src/test/java/demo/org/powermock/examples/simple/GreeterTest.java
new file mode 100644
index 0000000..ad8a405
--- /dev/null
+++ b/examples/simple/src/test/java/demo/org/powermock/examples/simple/GreeterTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.simple;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static junit.framework.Assert.assertEquals;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.reflect.Whitebox.invokeMethod;
+
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("demo.org.powermock.examples.simple.SimpleConfig")
+ at PrepareForTest( { Greeter.class, Logger.class })
+public class GreeterTest {
+
+ @Test
+ public void testGetMessage() throws Exception {
+ mockStatic(SimpleConfig.class);
+ expect(SimpleConfig.getGreeting()).andReturn("Hi");
+ expect(SimpleConfig.getTarget()).andReturn("All");
+ replay(SimpleConfig.class);
+
+ assertEquals("Hi All", invokeMethod(Greeter.class, "getMessage"));
+
+ verify(SimpleConfig.class);
+ }
+
+ @Test
+ public void testRun() throws Exception {
+ Logger logger = createMock(Logger.class);
+
+ expectNew(Logger.class).andReturn(logger);
+ logger.log("Hello");
+ expectLastCall().times(10);
+ replay(logger, Logger.class);
+
+ invokeMethod(new Greeter(), "run", 10, "Hello");
+
+ verify(logger, Logger.class);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testRunWhenLoggerThrowsUnexpectedRuntimeExeception() throws Exception {
+ expectNew(Logger.class).andThrow(new IllegalArgumentException("Unexpected exeception"));
+ replay(Logger.class);
+
+ invokeMethod(new Greeter(), "run", 10, "Hello");
+
+ verify(Logger.class);
+ }
+
+ /**
+ * This test demonstrates that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=110">issue
+ * 110</a> has been resolved.
+ */
+ @Test
+ @PrepareForTest( { SimpleConfig.class })
+ public void assertItsOkToInvokeReflectionMethodsOnClasses() throws Exception {
+ new SimpleConfig();
+ }
+}
\ No newline at end of file
diff --git a/examples/simple/src/test/java/demo/org/powermock/examples/simple/LoggerTest.java b/examples/simple/src/test/java/demo/org/powermock/examples/simple/LoggerTest.java
new file mode 100644
index 0000000..9ec3d74
--- /dev/null
+++ b/examples/simple/src/test/java/demo/org/powermock/examples/simple/LoggerTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.simple;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.Writer;
+
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { Logger.class })
+public class LoggerTest {
+
+ @Test(expected = IllegalStateException.class)
+ public void testException() throws Exception {
+ expectNew(FileWriter.class, "target/logger.log").andThrow(new IOException());
+
+ replayAll();
+ new Logger();
+ }
+
+ @Test
+ public void testLogger() throws Exception {
+ PrintWriter printWriter = createMock(PrintWriter.class);
+ printWriter.println("qwe");
+ expectNew(PrintWriter.class, new Class[] { Writer.class }, EasyMock.anyObject()).andReturn(printWriter);
+ replayAll();
+ Logger logger = new Logger();
+ logger.log("qwe");
+ verifyAll();
+ }
+
+ @Test
+ public void testLogger2() throws Exception {
+ PrintWriter printWriter = createMock(PrintWriter.class);
+ printWriter.println("qwe");
+ suppress(constructor(Logger.class));
+ replayAll();
+ Logger logger = new Logger();
+ Whitebox.setInternalState(logger, printWriter);
+ logger.log("qwe");
+ verifyAll();
+ }
+}
diff --git a/examples/slf4j-mockito/pom.xml b/examples/slf4j-mockito/pom.xml
new file mode 100644
index 0000000..1ed5bff
--- /dev/null
+++ b/examples/slf4j-mockito/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-slf4j-mockito</artifactId>
+ <name>slf4j-mockito</name>
+
+ <description>
+ Example of using Slf4jMockPolicy with Mockito.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.5.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/slf4j-mockito/src/main/java/demo/org/powermock/examples/Slf4jUser.java b/examples/slf4j-mockito/src/main/java/demo/org/powermock/examples/Slf4jUser.java
new file mode 100644
index 0000000..03e9bbe
--- /dev/null
+++ b/examples/slf4j-mockito/src/main/java/demo/org/powermock/examples/Slf4jUser.java
@@ -0,0 +1,13 @@
+package demo.org.powermock.examples;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Slf4jUser {
+ private static final Logger log = LoggerFactory.getLogger(Slf4jUser.class);
+
+ public final String getMessage() {
+ log.debug("getMessage!");
+ return "log4j user";
+ }
+}
diff --git a/examples/slf4j-mockito/src/main/resources/log4j.properties b/examples/slf4j-mockito/src/main/resources/log4j.properties
new file mode 100644
index 0000000..5014d08
--- /dev/null
+++ b/examples/slf4j-mockito/src/main/resources/log4j.properties
@@ -0,0 +1,8 @@
+log4j.rootLogger=WARN, R
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=${catalina.home}/logs/admin-webapp.log
+log4j.appender.R.File.Suffix=
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=10
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%p %d{ABSOLUTE} %c:%L %x - %m%n
\ No newline at end of file
diff --git a/examples/slf4j-mockito/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java b/examples/slf4j-mockito/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java
new file mode 100644
index 0000000..822a295
--- /dev/null
+++ b/examples/slf4j-mockito/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java
@@ -0,0 +1,29 @@
+package demo.org.powermock.examples;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.mockpolicies.Slf4jMockPolicy;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.slf4j.Logger;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Unit tests that assert that the {@link Slf4jMockPolicy} works for Mockito.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(Slf4jMockPolicy.class)
+public class Slf4jUserTest {
+
+ @Test
+ public void assertSlf4jMockPolicyWorks() throws Exception {
+ final Slf4jUser tested = new Slf4jUser();
+
+ tested.getMessage();
+
+ final Class<? extends Logger> aClass = Whitebox.getInternalState(Slf4jUser.class, Logger.class).getClass();
+ assertTrue(aClass.getName().contains("EnhancerByMockitoWithCGLIB"));
+ }
+}
diff --git a/examples/slf4j-noimpl/pom.xml b/examples/slf4j-noimpl/pom.xml
new file mode 100644
index 0000000..52f427f
--- /dev/null
+++ b/examples/slf4j-noimpl/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-slf4j-no-impl</artifactId>
+ <name>slf4j-mockito</name>
+
+ <description>
+ Example of using Slf4jMockPolicy with no slf4j implementation (only API).
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ </dependency>
+
+ <!-- test and mocking tools -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/slf4j-noimpl/src/main/java/demo/org/powermock/examples/SL4JUser.java b/examples/slf4j-noimpl/src/main/java/demo/org/powermock/examples/SL4JUser.java
new file mode 100755
index 0000000..a3c47e5
--- /dev/null
+++ b/examples/slf4j-noimpl/src/main/java/demo/org/powermock/examples/SL4JUser.java
@@ -0,0 +1,14 @@
+package demo.org.powermock.examples;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class SL4JUser {
+ final Logger logger = LoggerFactory.getLogger(SL4JUser.class);
+
+ public boolean returnTrue() {
+ logger.info("ikk");
+ return true;
+ }
+}
diff --git a/examples/slf4j-noimpl/src/test/java/demo/org/powermock/examples/SPITest.java b/examples/slf4j-noimpl/src/test/java/demo/org/powermock/examples/SPITest.java
new file mode 100755
index 0000000..fe70be9
--- /dev/null
+++ b/examples/slf4j-noimpl/src/test/java/demo/org/powermock/examples/SPITest.java
@@ -0,0 +1,23 @@
+package demo.org.powermock.examples;
+
+import static org.junit.Assert.*;
+
+import demo.org.powermock.examples.SL4JUser;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.mockpolicies.Slf4jMockPolicy;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(Slf4jMockPolicy.class)
+public class SPITest {
+
+ @Test
+ public void powerMockCanLoadClassesThatHaveMethodsAndFieldsReturningClassesThatAreNotInClasspath() throws Exception {
+ SL4JUser obj = new SL4JUser();
+ assertTrue(obj.returnTrue());
+ }
+
+}
diff --git a/examples/slf4j/pom.xml b/examples/slf4j/pom.xml
new file mode 100644
index 0000000..ba3fbf7
--- /dev/null
+++ b/examples/slf4j/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-slf4j</artifactId>
+ <name>slf4j</name>
+
+ <description>
+ Example of using Slf4jMockPolicy.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.5.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>1.5.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/slf4j/src/main/java/demo/org/powermock/examples/Slf4jUser.java b/examples/slf4j/src/main/java/demo/org/powermock/examples/Slf4jUser.java
new file mode 100644
index 0000000..89289b2
--- /dev/null
+++ b/examples/slf4j/src/main/java/demo/org/powermock/examples/Slf4jUser.java
@@ -0,0 +1,13 @@
+package demo.org.powermock.examples;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Slf4jUser {
+ private static final Logger log = LoggerFactory.getLogger(Slf4jUser.class);
+
+ public final String getMessage() {
+ log.debug("getMessage!");
+ return "log4j user";
+ }
+}
diff --git a/examples/slf4j/src/main/resources/log4j.properties b/examples/slf4j/src/main/resources/log4j.properties
new file mode 100644
index 0000000..5014d08
--- /dev/null
+++ b/examples/slf4j/src/main/resources/log4j.properties
@@ -0,0 +1,8 @@
+log4j.rootLogger=WARN, R
+log4j.appender.R=org.apache.log4j.RollingFileAppender
+log4j.appender.R.File=${catalina.home}/logs/admin-webapp.log
+log4j.appender.R.File.Suffix=
+log4j.appender.R.MaxFileSize=10MB
+log4j.appender.R.MaxBackupIndex=10
+log4j.appender.R.layout=org.apache.log4j.PatternLayout
+log4j.appender.R.layout.ConversionPattern=%p %d{ABSOLUTE} %c:%L %x - %m%n
\ No newline at end of file
diff --git a/examples/slf4j/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java b/examples/slf4j/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java
new file mode 100644
index 0000000..4332baa
--- /dev/null
+++ b/examples/slf4j/src/test/java/demo/org/powermock/examples/Slf4jUserTest.java
@@ -0,0 +1,35 @@
+package demo.org.powermock.examples;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.mockpolicies.Slf4jMockPolicy;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.slf4j.Logger;
+
+import java.lang.reflect.Proxy;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Unit tests that assert that the {@link Slf4jMockPolicy} works.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(Slf4jMockPolicy.class)
+public class Slf4jUserTest {
+
+ @Test
+ public void assertSlf4jMockPolicyWorks() throws Exception {
+ final Slf4jUser tested = new Slf4jUser();
+
+ replayAll();
+
+ tested.getMessage();
+
+ assertTrue(Proxy.isProxyClass(Whitebox.getInternalState(Slf4jUser.class, Logger.class).getClass()));
+ verifyAll();
+ }
+}
diff --git a/examples/spring-easymock/pom.xml b/examples/spring-easymock/pom.xml
new file mode 100644
index 0000000..a590ca2
--- /dev/null
+++ b/examples/spring-easymock/pom.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-spring-easymock</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <spring.version>3.0.5.RELEASE</spring.version>
+ </properties>
+
+ <description>
+ Example showing how to use the PowerMock in a Spring Integration Test
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/spring-easymock/src/main/java/powermock/examples/spring/FinalClass.java b/examples/spring-easymock/src/main/java/powermock/examples/spring/FinalClass.java
new file mode 100644
index 0000000..1d9dfd3
--- /dev/null
+++ b/examples/spring-easymock/src/main/java/powermock/examples/spring/FinalClass.java
@@ -0,0 +1,14 @@
+package powermock.examples.spring;
+
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ */
+ at Component
+public final class FinalClass {
+
+ public final String sayHello(){
+ return "Hello, man!";
+ }
+}
diff --git a/examples/spring-easymock/src/main/java/powermock/examples/spring/IdGenerator.java b/examples/spring-easymock/src/main/java/powermock/examples/spring/IdGenerator.java
new file mode 100644
index 0000000..068ee8a
--- /dev/null
+++ b/examples/spring-easymock/src/main/java/powermock/examples/spring/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.spring;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/spring-easymock/src/main/java/powermock/examples/spring/Message.java b/examples/spring-easymock/src/main/java/powermock/examples/spring/Message.java
new file mode 100644
index 0000000..eaeebd3
--- /dev/null
+++ b/examples/spring-easymock/src/main/java/powermock/examples/spring/Message.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+public class Message {
+ private final long id;
+ private final String content;
+
+ public Message(long id, String content) {
+ this.id = id;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/examples/spring-easymock/src/main/java/powermock/examples/spring/MyBean.java b/examples/spring-easymock/src/main/java/powermock/examples/spring/MyBean.java
new file mode 100644
index 0000000..dce123d
--- /dev/null
+++ b/examples/spring-easymock/src/main/java/powermock/examples/spring/MyBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+ at Component
+public class MyBean {
+
+ @Autowired
+ private FinalClass finalClass;
+
+ public String sayHello(){
+ return finalClass.sayHello();
+ }
+
+ public Message generateMessage() {
+ final long id = IdGenerator.generateNewId();
+ return new Message(id, "My bean message");
+ }
+}
diff --git a/examples/spring-easymock/src/main/resources/example-context.xml b/examples/spring-easymock/src/main/resources/example-context.xml
new file mode 100644
index 0000000..145ba8b
--- /dev/null
+++ b/examples/spring-easymock/src/main/resources/example-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="powermock.examples.spring" />
+
+</beans>
\ No newline at end of file
diff --git a/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
new file mode 100644
index 0000000..3f70388
--- /dev/null
+++ b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
@@ -0,0 +1,84 @@
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import powermock.examples.spring.IdGenerator;
+import powermock.examples.spring.Message;
+import powermock.examples.spring.MyBean;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ *
+ */
+ at ContextConfiguration("classpath:/example-context.xml")
+public abstract class SpringExampleTest {
+ @Autowired
+ private MyBean myBean;
+
+ @Test
+ public void mockStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ expect(IdGenerator.generateNewId()).andReturn(expectedId);
+ replay(IdGenerator.class);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void mockStaticMethodAndVerify() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ expect(IdGenerator.generateNewId()).andReturn(expectedId);
+ replay(IdGenerator.class);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void stubStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ stub(method(IdGenerator.class, "generateNewId")).toReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void suppressStaticMethod() throws Exception {
+ // Given
+ suppress(method(IdGenerator.class, "generateNewId"));
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(0L, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+}
diff --git a/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java
new file mode 100644
index 0000000..0e88293
--- /dev/null
+++ b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java
@@ -0,0 +1,39 @@
+package org.powermock.examples.spring.mockito;
+
+import org.easymock.TestSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.spring.FinalClass;
+import powermock.examples.spring.MyBean;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.junit.Assert.assertEquals;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalClass.class)
+public class SpringInjectFinalClassExampleTest {
+
+ @Mock
+ private FinalClass finalClass;
+
+ @TestSubject
+ private MyBean myBean = new MyBean();;
+
+ @Test
+ public void testInjectFinalClass() {
+ final String value = "What's up?";
+ expect(finalClass.sayHello()).andReturn(value);
+ replay(finalClass);
+
+ assertEquals(value, myBean.sayHello());
+
+ }
+
+}
diff --git a/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithDelegateRunnerExampleTest.java b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithDelegateRunnerExampleTest.java
new file mode 100644
index 0000000..e53aece
--- /dev/null
+++ b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithDelegateRunnerExampleTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
+ at PrepareForTest(IdGenerator.class)
+public class SpringWithDelegateRunnerExampleTest extends SpringExampleTest {
+
+}
diff --git a/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithRuleExampleTest.java b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithRuleExampleTest.java
new file mode 100644
index 0000000..8bf62a6
--- /dev/null
+++ b/examples/spring-easymock/src/test/java/org/powermock/examples/spring/mockito/SpringWithRuleExampleTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Rule;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+
+ at RunWith(SpringJUnit4ClassRunner.class)
+ at ContextConfiguration("classpath:/example-context.xml")
+ at PrepareForTest(IdGenerator.class)
+public class SpringWithRuleExampleTest extends SpringExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+}
diff --git a/examples/spring-mockito-delegate/pom.xml b/examples/spring-mockito-delegate/pom.xml
new file mode 100644
index 0000000..d7b43b7
--- /dev/null
+++ b/examples/spring-mockito-delegate/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-spring-mockito-delegate</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <spring.version>3.0.5.RELEASE</spring.version>
+ </properties>
+
+ <description>
+ Example showing how to use the PowerMock in a Spring Integration Test
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/IdGenerator.java b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/IdGenerator.java
new file mode 100644
index 0000000..092a37a
--- /dev/null
+++ b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.spring;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/Message.java b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/Message.java
new file mode 100644
index 0000000..eaeebd3
--- /dev/null
+++ b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/Message.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+public class Message {
+ private final long id;
+ private final String content;
+
+ public Message(long id, String content) {
+ this.id = id;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/MyBean.java b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/MyBean.java
new file mode 100644
index 0000000..cc2a806
--- /dev/null
+++ b/examples/spring-mockito-delegate/src/main/java/powermock/examples/spring/MyBean.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+import org.springframework.stereotype.Component;
+
+ at Component
+public class MyBean {
+
+ public Message generateMessage() {
+ final long id = IdGenerator.generateNewId();
+ return new Message(id, "My bean message");
+ }
+}
diff --git a/examples/spring-mockito-delegate/src/main/resources/example-context.xml b/examples/spring-mockito-delegate/src/main/resources/example-context.xml
new file mode 100644
index 0000000..145ba8b
--- /dev/null
+++ b/examples/spring-mockito-delegate/src/main/resources/example-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="powermock.examples.spring" />
+
+</beans>
\ No newline at end of file
diff --git a/examples/spring-mockito-delegate/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java b/examples/spring-mockito-delegate/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
new file mode 100644
index 0000000..9e13bb5
--- /dev/null
+++ b/examples/spring-mockito-delegate/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+import powermock.examples.spring.Message;
+import powermock.examples.spring.MyBean;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
+ at ContextConfiguration("classpath:/example-context.xml")
+ at PrepareForTest(IdGenerator.class)
+/* @PowermMockIgnore can sometimes help performance: */
+//@PowerMockIgnore({"com.sun.*", "org.w3c.*", "javax.xml.*", "org.xml.*"})
+public class SpringExampleTest {
+
+ @Autowired
+ private MyBean myBean;
+
+ @Test
+ public void mockStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void mockStaticMethodAndVerify() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ verifyStatic(); IdGenerator.generateNewId();
+ }
+
+ @Test
+ public void stubStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ stub(method(IdGenerator.class, "generateNewId")).toReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void suppressStaticMethod() throws Exception {
+ // Given
+ suppress(method(IdGenerator.class, "generateNewId"));
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(0L, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+}
diff --git a/examples/spring-mockito-xml-agent/pom.xml b/examples/spring-mockito-xml-agent/pom.xml
new file mode 100644
index 0000000..a898d9b
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-spring-mockito-xml-agent</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <spring.version>3.0.5.RELEASE</spring.version>
+ </properties>
+
+ <description>
+ Example showing how to use the PowerMock in a Spring Integration Test with PowerMock java agent bootstrap
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/CompanyRepository.java b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/CompanyRepository.java
new file mode 100644
index 0000000..4a49528
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/CompanyRepository.java
@@ -0,0 +1,45 @@
+package powermock.examples.spring;
+
+import org.springframework.stereotype.Repository;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.util.LinkedList;
+import java.util.List;
+
+ at Repository
+public class CompanyRepository {
+
+ public String[] getAllEmployees() {
+ try {
+ final List<String> employees = new LinkedList<String>();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(getClass().getResourceAsStream("/employees.xml"));
+ doc.getDocumentElement().normalize();
+ NodeList nodeLst = doc.getElementsByTagName("employee");
+ for (int s = 0; s < nodeLst.getLength(); s++) {
+ Node fstNode = nodeLst.item(s);
+ if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element fstElmnt = (Element) fstNode;
+ NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("firstname");
+ Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
+ NodeList fstNm = fstNmElmnt.getChildNodes();
+ final String firstName = fstNm.item(0).getNodeValue();
+ NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("lastname");
+ Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
+ NodeList lstNm = lstNmElmnt.getChildNodes();
+ final String lastName = lstNm.item(0).getNodeValue();
+ employees.add(String.format("%s %s", firstName, lastName));
+ }
+ }
+ return employees.toArray(new String[employees.size()]);
+ }catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/IdGenerator.java b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/IdGenerator.java
new file mode 100644
index 0000000..092a37a
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.spring;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/Message.java b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/Message.java
new file mode 100644
index 0000000..eaeebd3
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/Message.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+public class Message {
+ private final long id;
+ private final String content;
+
+ public Message(long id, String content) {
+ this.id = id;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/MyBean.java b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/MyBean.java
new file mode 100644
index 0000000..e9215e3
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/java/powermock/examples/spring/MyBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.xml.sax.SAXException;
+
+ at Component
+public class MyBean {
+
+ @Autowired
+ private CompanyRepository companyRepository;
+
+ public Message generateMessage() throws SAXException {
+ final String[] allEmployees = companyRepository.getAllEmployees();
+ final String message = StringUtils.join(allEmployees, ", ");
+
+ final long id = IdGenerator.generateNewId();
+ return new Message(id, message);
+ }
+}
diff --git a/examples/spring-mockito-xml-agent/src/main/resources/employees.xml b/examples/spring-mockito-xml-agent/src/main/resources/employees.xml
new file mode 100644
index 0000000..d30984d
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/resources/employees.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<company>
+ <employee>
+ <firstname>John</firstname>
+ <lastname>Doe</lastname>
+ </employee>
+ <employee>
+ <firstname>Paul</firstname>
+ <lastname>Anderson</lastname>
+ </employee>
+ <employee>
+ <firstname>Jane</firstname>
+ <lastname>Doe</lastname>
+ </employee>
+</company>
\ No newline at end of file
diff --git a/examples/spring-mockito-xml-agent/src/main/resources/example-context.xml b/examples/spring-mockito-xml-agent/src/main/resources/example-context.xml
new file mode 100644
index 0000000..145ba8b
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/main/resources/example-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="powermock.examples.spring" />
+
+</beans>
\ No newline at end of file
diff --git a/examples/spring-mockito-xml-agent/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java b/examples/spring-mockito-xml-agent/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
new file mode 100644
index 0000000..1460002
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+import powermock.examples.spring.Message;
+import powermock.examples.spring.MyBean;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(SpringJUnit4ClassRunner.class)
+ at ContextConfiguration("classpath:/example-context.xml")
+ at PrepareForTest(IdGenerator.class)
+public class SpringExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Autowired
+ private MyBean myBean;
+
+ @Test
+ public void mockStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+
+ @Test
+ public void mockStaticMethodAndVerify() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ verifyStatic(); IdGenerator.generateNewId();
+ }
+
+ @Test
+ public void stubStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ stub(method(IdGenerator.class, "generateNewId")).toReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+
+ @Test
+ public void suppressStaticMethod() throws Exception {
+ // Given
+ suppress(method(IdGenerator.class, "generateNewId"));
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(0L, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+
+}
diff --git a/examples/spring-mockito-xml-agent/src/test/java/org/powermock/modules/agent/AbstractClassTransformerTest.java b/examples/spring-mockito-xml-agent/src/test/java/org/powermock/modules/agent/AbstractClassTransformerTest.java
new file mode 100644
index 0000000..8b5123a
--- /dev/null
+++ b/examples/spring-mockito-xml-agent/src/test/java/org/powermock/modules/agent/AbstractClassTransformerTest.java
@@ -0,0 +1,21 @@
+package org.powermock.modules.agent;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class AbstractClassTransformerTest {
+
+ @Test public void
+ replace_slash_with_dots_method_replaces_slashes_with_dots() {
+ // Given
+ AbstractClassTransformer abstractClassTransformer = new AbstractClassTransformer() { };
+
+ // When
+ String replaced = abstractClassTransformer.replaceSlashWithDots("org/powermock/core/Main");
+
+ // Then
+ assertThat(replaced, equalTo("org.powermock.core.Main"));
+ }
+}
\ No newline at end of file
diff --git a/examples/spring-mockito-xml/pom.xml b/examples/spring-mockito-xml/pom.xml
new file mode 100644
index 0000000..b258ffd
--- /dev/null
+++ b/examples/spring-mockito-xml/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-spring-mockito-xml</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <spring.version>3.0.5.RELEASE</spring.version>
+ </properties>
+
+ <description>
+ Example showing how to use the PowerMock in a Spring Integration Test and XML parsing
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/CompanyRepository.java b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/CompanyRepository.java
new file mode 100644
index 0000000..4a49528
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/CompanyRepository.java
@@ -0,0 +1,45 @@
+package powermock.examples.spring;
+
+import org.springframework.stereotype.Repository;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.util.LinkedList;
+import java.util.List;
+
+ at Repository
+public class CompanyRepository {
+
+ public String[] getAllEmployees() {
+ try {
+ final List<String> employees = new LinkedList<String>();
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ Document doc = db.parse(getClass().getResourceAsStream("/employees.xml"));
+ doc.getDocumentElement().normalize();
+ NodeList nodeLst = doc.getElementsByTagName("employee");
+ for (int s = 0; s < nodeLst.getLength(); s++) {
+ Node fstNode = nodeLst.item(s);
+ if (fstNode.getNodeType() == Node.ELEMENT_NODE) {
+ Element fstElmnt = (Element) fstNode;
+ NodeList fstNmElmntLst = fstElmnt.getElementsByTagName("firstname");
+ Element fstNmElmnt = (Element) fstNmElmntLst.item(0);
+ NodeList fstNm = fstNmElmnt.getChildNodes();
+ final String firstName = fstNm.item(0).getNodeValue();
+ NodeList lstNmElmntLst = fstElmnt.getElementsByTagName("lastname");
+ Element lstNmElmnt = (Element) lstNmElmntLst.item(0);
+ NodeList lstNm = lstNmElmnt.getChildNodes();
+ final String lastName = lstNm.item(0).getNodeValue();
+ employees.add(String.format("%s %s", firstName, lastName));
+ }
+ }
+ return employees.toArray(new String[employees.size()]);
+ }catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/IdGenerator.java b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/IdGenerator.java
new file mode 100644
index 0000000..5558a65
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.spring;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public final class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/Message.java b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/Message.java
new file mode 100644
index 0000000..eaeebd3
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/Message.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+public class Message {
+ private final long id;
+ private final String content;
+
+ public Message(long id, String content) {
+ this.id = id;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/MyBean.java b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/MyBean.java
new file mode 100644
index 0000000..e9215e3
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/java/powermock/examples/spring/MyBean.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.xml.sax.SAXException;
+
+ at Component
+public class MyBean {
+
+ @Autowired
+ private CompanyRepository companyRepository;
+
+ public Message generateMessage() throws SAXException {
+ final String[] allEmployees = companyRepository.getAllEmployees();
+ final String message = StringUtils.join(allEmployees, ", ");
+
+ final long id = IdGenerator.generateNewId();
+ return new Message(id, message);
+ }
+}
diff --git a/examples/spring-mockito-xml/src/main/resources/employees.xml b/examples/spring-mockito-xml/src/main/resources/employees.xml
new file mode 100644
index 0000000..d30984d
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/resources/employees.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<company>
+ <employee>
+ <firstname>John</firstname>
+ <lastname>Doe</lastname>
+ </employee>
+ <employee>
+ <firstname>Paul</firstname>
+ <lastname>Anderson</lastname>
+ </employee>
+ <employee>
+ <firstname>Jane</firstname>
+ <lastname>Doe</lastname>
+ </employee>
+</company>
\ No newline at end of file
diff --git a/examples/spring-mockito-xml/src/main/resources/example-context.xml b/examples/spring-mockito-xml/src/main/resources/example-context.xml
new file mode 100644
index 0000000..145ba8b
--- /dev/null
+++ b/examples/spring-mockito-xml/src/main/resources/example-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="powermock.examples.spring" />
+
+</beans>
\ No newline at end of file
diff --git a/examples/spring-mockito-xml/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java b/examples/spring-mockito-xml/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
new file mode 100644
index 0000000..1f0f578
--- /dev/null
+++ b/examples/spring-mockito-xml/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+import powermock.examples.spring.Message;
+import powermock.examples.spring.MyBean;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(SpringJUnit4ClassRunner.class)
+ at ContextConfiguration("classpath:/example-context.xml")
+ at PrepareForTest(IdGenerator.class)
+ at PowerMockIgnore({"org.w3c.*", "javax.xml.*"})
+public class SpringExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Autowired
+ private MyBean myBean;
+
+ @Test
+ public void mockStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+
+ @Test
+ public void mockStaticMethodAndVerify() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ verifyStatic(); IdGenerator.generateNewId();
+ }
+
+ @Test
+ public void stubStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ stub(method(IdGenerator.class, "generateNewId")).toReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+
+ @Test
+ public void suppressStaticMethod() throws Exception {
+ // Given
+ suppress(method(IdGenerator.class, "generateNewId"));
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(0L, message.getId());
+ assertEquals("John Doe, Paul Anderson, Jane Doe", message.getContent());
+ }
+}
\ No newline at end of file
diff --git a/examples/spring-mockito/pom.xml b/examples/spring-mockito/pom.xml
new file mode 100644
index 0000000..980c23d
--- /dev/null
+++ b/examples/spring-mockito/pom.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-examples-spring-mockito</artifactId>
+ <name>${project.artifactId}</name>
+ <properties>
+ <spring.version>3.0.5.RELEASE</spring.version>
+ </properties>
+
+ <description>
+ Example showing how to use the PowerMock in a Spring Integration Test
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${spring.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${spring.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/examples/spring-mockito/src/main/java/powermock/examples/spring/FinalClass.java b/examples/spring-mockito/src/main/java/powermock/examples/spring/FinalClass.java
new file mode 100644
index 0000000..1d9dfd3
--- /dev/null
+++ b/examples/spring-mockito/src/main/java/powermock/examples/spring/FinalClass.java
@@ -0,0 +1,14 @@
+package powermock.examples.spring;
+
+import org.springframework.stereotype.Component;
+
+/**
+ *
+ */
+ at Component
+public final class FinalClass {
+
+ public final String sayHello(){
+ return "Hello, man!";
+ }
+}
diff --git a/examples/spring-mockito/src/main/java/powermock/examples/spring/IdGenerator.java b/examples/spring-mockito/src/main/java/powermock/examples/spring/IdGenerator.java
new file mode 100644
index 0000000..092a37a
--- /dev/null
+++ b/examples/spring-mockito/src/main/java/powermock/examples/spring/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.examples.spring;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/spring-mockito/src/main/java/powermock/examples/spring/Message.java b/examples/spring-mockito/src/main/java/powermock/examples/spring/Message.java
new file mode 100644
index 0000000..eaeebd3
--- /dev/null
+++ b/examples/spring-mockito/src/main/java/powermock/examples/spring/Message.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+public class Message {
+ private final long id;
+ private final String content;
+
+ public Message(long id, String content) {
+ this.id = id;
+ this.content = content;
+ }
+
+ public long getId() {
+ return id;
+ }
+
+ public String getContent() {
+ return content;
+ }
+}
diff --git a/examples/spring-mockito/src/main/java/powermock/examples/spring/MyBean.java b/examples/spring-mockito/src/main/java/powermock/examples/spring/MyBean.java
new file mode 100644
index 0000000..dce123d
--- /dev/null
+++ b/examples/spring-mockito/src/main/java/powermock/examples/spring/MyBean.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package powermock.examples.spring;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+ at Component
+public class MyBean {
+
+ @Autowired
+ private FinalClass finalClass;
+
+ public String sayHello(){
+ return finalClass.sayHello();
+ }
+
+ public Message generateMessage() {
+ final long id = IdGenerator.generateNewId();
+ return new Message(id, "My bean message");
+ }
+}
diff --git a/examples/spring-mockito/src/main/resources/example-context.xml b/examples/spring-mockito/src/main/resources/example-context.xml
new file mode 100644
index 0000000..145ba8b
--- /dev/null
+++ b/examples/spring-mockito/src/main/resources/example-context.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-2.5.xsd">
+
+ <context:component-scan base-package="powermock.examples.spring" />
+
+</beans>
\ No newline at end of file
diff --git a/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java b/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
new file mode 100644
index 0000000..b545be5
--- /dev/null
+++ b/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringExampleTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import powermock.examples.spring.IdGenerator;
+import powermock.examples.spring.Message;
+import powermock.examples.spring.MyBean;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(SpringJUnit4ClassRunner.class)
+ at ContextConfiguration("classpath:/example-context.xml")
+ at PrepareForTest(IdGenerator.class)
+public class SpringExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Autowired
+ private MyBean myBean;
+
+ @Test
+ public void mockStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void mockStaticMethodAndVerify() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ mockStatic(IdGenerator.class);
+ when(IdGenerator.generateNewId()).thenReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ verifyStatic(); IdGenerator.generateNewId();
+ }
+
+ @Test
+ public void stubStaticMethod() throws Exception {
+ // Given
+ final long expectedId = 2L;
+ stub(method(IdGenerator.class, "generateNewId")).toReturn(expectedId);
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(expectedId, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+ @Test
+ public void suppressStaticMethod() throws Exception {
+ // Given
+ suppress(method(IdGenerator.class, "generateNewId"));
+
+ // When
+ final Message message = myBean.generateMessage();
+
+ // Then
+ assertEquals(0L, message.getId());
+ assertEquals("My bean message", message.getContent());
+ }
+
+}
diff --git a/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java b/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java
new file mode 100644
index 0000000..022528d
--- /dev/null
+++ b/examples/spring-mockito/src/test/java/org/powermock/examples/spring/mockito/SpringInjectFinalClassExampleTest.java
@@ -0,0 +1,37 @@
+package org.powermock.examples.spring.mockito;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import powermock.examples.spring.FinalClass;
+import powermock.examples.spring.MyBean;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalClass.class)
+public class SpringInjectFinalClassExampleTest {
+
+ @Mock
+ private FinalClass finalClass;
+
+ @InjectMocks
+ private MyBean myBean = new MyBean();;
+
+ @Test
+ public void testInjectFinalClass() {
+ final String value = "What's up?";
+ when(finalClass.sayHello()).thenReturn(value);
+
+ assertEquals(value, myBean.sayHello());
+
+ }
+
+}
diff --git a/examples/tutorial/pom.xml b/examples/tutorial/pom.xml
new file mode 100644
index 0000000..fb848b0
--- /dev/null
+++ b/examples/tutorial/pom.xml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.powermock.examples</groupId>
+ <artifactId>powermock-examples-tutorial</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <name>tutorial</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ Code examples used in the PowerMock tutorial.
+ </description>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:svn:https://powermock.googlecode.com/svn/trunk/examples/tutorial</connection>
+ <developerConnection>scm:svn:https://powermock.googlecode.com/svn/trunk/examples/tutorial</developerConnection>
+ <url>http://code.google.com/p/powermock/source/browse/trunk/examples/tutorial</url>
+ </scm>
+ <distributionManagement>
+ <repository>
+ <uniqueVersion>false</uniqueVersion>
+ <id>file</id>
+ <name>Local file Repository</name>
+ <url>file:./../../repo</url>
+ <layout>default</layout>
+ </repository>
+ <site>
+ <id>powermock-local</id>
+ <name>Local Site</name>
+ <url>target/site</url>
+ </site>
+ </distributionManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <profiles>
+ <profile>
+ <id>tutorial</id>
+ <properties>
+ <testcode>tutorial</testcode>
+ </properties>
+ </profile>
+ <profile>
+ <id>solution</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <properties>
+ <testcode>solution</testcode>
+ </properties>
+ </profile>
+ </profiles>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.2</version>
+ <configuration>
+ <verbose>true</verbose>
+ <source>1.6</source>
+ <target>1.6</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ <testSourceDirectory>src/${testcode}/java</testSourceDirectory>
+ </build>
+</project>
diff --git a/examples/tutorial/readme.txt b/examples/tutorial/readme.txt
new file mode 100644
index 0000000..2f5413b
--- /dev/null
+++ b/examples/tutorial/readme.txt
@@ -0,0 +1,34 @@
+Tutorial instructions
+---------------------
+
+Write test cases for all the "production" code. Suggested order:
+1) Test hellopower HelloWorld
+2) Test staticmocking ServiceRegistrator
+3) Test partialmocking ProviderServiceImpl
+4) Test domainmocking SampleServiceImpl
+
+
+Command line:
+* mvn test -P tutorial
+
+Eclipse users:
+* mvn eclipse:eclipse
+* Manaully add the folder src/tutorial/java to the build path
+
+
+This tutorial contains 3 different source folders:
+main - the "production" code which should be tested
+solution - test cases that tests all the "production" code
+tutorial - skeleton test cases which you should use to create your test cases
+
+
+Notice that the sub package "withoutpowermock" contains refactored "production"
+code and traditional test cases that doesn't use PowerMock. Of course, there
+are typically several ways to refactor the code and we have only shown one
+example solution.
+
+
+!Important!
+
+The code here is only intended as a tutorial for how to use various PowerMock
+techniques and not a recommended way of coding!
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/common/annotation/Inject.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/common/annotation/Inject.java
new file mode 100644
index 0000000..643119a
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/common/annotation/Inject.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.common.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * A custom marker annotation to demonstrate how to use PowerMock to set field
+ * dependencies. In a real application these dependencies are set by an external
+ * dependency injection framework using reflection.
+ */
+ at Target( { ElementType.FIELD, ElementType.CONSTRUCTOR })
+ at Retention(RetentionPolicy.RUNTIME)
+ at Documented
+public @interface Inject {
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/EventService.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/EventService.java
new file mode 100644
index 0000000..90d0e58
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/EventService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking;
+
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+
+/**
+ * A simple interface that manages events.
+ */
+public interface EventService {
+
+ /**
+ * Sends a new error event to the interested parties in the system.
+ *
+ * @param person
+ * The person to object associated with this event.
+ * @param messages
+ * The business messages object that may contain errors or
+ * warnings.
+ */
+ void sendErrorEvent(Person person, BusinessMessages messages);
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/PersonService.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/PersonService.java
new file mode 100644
index 0000000..db8ff55
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/PersonService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking;
+
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+
+/**
+ * A simple interface that manages persons.
+ */
+public interface PersonService {
+
+ /**
+ * Create a new person.
+ *
+ * @param person
+ * The person to create.
+ * @param messages
+ * The business messages object to be filled with validation
+ * errors.
+ */
+ void create(Person person, BusinessMessages messages);
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/SampleService.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/SampleService.java
new file mode 100644
index 0000000..1e59e4d
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/SampleService.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking;
+
+/**
+ * A simple service interface.
+ */
+public interface SampleService {
+
+ /**
+ * Create a new person based on the following parameters and store it in the
+ * underlying persistence store. The service will notify the result of the
+ * operation to an event service.
+ *
+ * @param firstName
+ * The first name of the person to create.
+ * @param lastName
+ * The last name of the person to create.
+ * @return <code>true</code> if the person was created successfully,
+ * <code>false</code> otherwise.
+ */
+ boolean createPerson(String firstName, String lastName);
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/BusinessMessages.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/BusinessMessages.java
new file mode 100644
index 0000000..2aa9f7e
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/BusinessMessages.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.domain;
+
+import java.util.Random;
+
+/**
+ * A simple domain object that's pretended to hold state of one or more
+ * operation outcomes. We pretend that services can store messages or errors
+ * (for example validation errors) in this message (even though these methods
+ * are not implemented or even defined here).
+ */
+public class BusinessMessages {
+
+ /**
+ * @return <code>true</code> if the an error has occurred when invoking an
+ * operation, <code>false</code> otherwise.
+ */
+ public boolean hasErrors() {
+ return new Random().nextBoolean();
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/Person.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/Person.java
new file mode 100644
index 0000000..29d63b2
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/Person.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.domain;
+
+/**
+ * A simple domain object used in this example.
+ */
+public class Person {
+
+ private final String firstName;
+ private final String lastName;
+
+ public Person(String firstName, String lastName) {
+ if (firstName == null || lastName == null) {
+ throw new IllegalArgumentException("First name or last name cannot be null");
+ }
+ this.firstName = firstName;
+ this.lastName = lastName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
+ result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final Person other = (Person) obj;
+ if (firstName == null) {
+ if (other.firstName != null)
+ return false;
+ } else if (!firstName.equals(other.firstName))
+ return false;
+ if (lastName == null) {
+ if (other.lastName != null)
+ return false;
+ } else if (!lastName.equals(other.lastName))
+ return false;
+ return true;
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/SampleServiceException.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/SampleServiceException.java
new file mode 100644
index 0000000..f3c4031
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/domain/SampleServiceException.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.domain;
+
+/**
+ * A simple exception that's thrown when an error occurs when executing a method
+ * in the SampleService.
+ */
+public class SampleServiceException extends RuntimeException {
+ private static final long serialVersionUID = -4496776468570486636L;
+
+ public SampleServiceException(String description, Throwable cause) {
+ super(description, cause);
+ }
+
+ public SampleServiceException(String description) {
+ super(description);
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImpl.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImpl.java
new file mode 100644
index 0000000..0329b51
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImpl.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.impl;
+
+import demo.org.powermock.examples.tutorial.domainmocking.EventService;
+import demo.org.powermock.examples.tutorial.domainmocking.PersonService;
+import demo.org.powermock.examples.tutorial.domainmocking.SampleService;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.SampleServiceException;
+
+/**
+ * This is a simple service that delegates calls to two stub services. The
+ * purpose of this service is to demonstrate that need to mock instantiation of
+ * domain objects.
+ */
+public class SampleServiceImpl implements SampleService {
+
+ private final PersonService personService;
+
+ private final EventService eventService;
+
+ /**
+ * Creates a new instance of the SampleServiceImpl with the following
+ * collaborators.
+ *
+ * @param personService
+ * The person service to use.
+ * @param eventService
+ * The event service to use.
+ */
+ public SampleServiceImpl(PersonService personService, EventService eventService) {
+ this.personService = personService;
+ this.eventService = eventService;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean createPerson(String firstName, String lastName) {
+ BusinessMessages messages = new BusinessMessages();
+ Person person = null;
+ try {
+ person = new Person(firstName, lastName);
+ } catch (IllegalArgumentException e) {
+ throw new SampleServiceException(e.getMessage(), e);
+ }
+
+ personService.create(person, messages);
+
+ final boolean hasErrors = messages.hasErrors();
+ if (hasErrors) {
+ eventService.sendErrorEvent(person, messages);
+ }
+
+ return !hasErrors;
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImpl.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImpl.java
new file mode 100644
index 0000000..36cf166
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImpl.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.domainmocking.EventService;
+import demo.org.powermock.examples.tutorial.domainmocking.PersonService;
+import demo.org.powermock.examples.tutorial.domainmocking.SampleService;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.SampleServiceException;
+
+/**
+ * This is a simple service that delegates calls to two stub services. The
+ * purpose of this service is to demonstrate that need to refactor the
+ * production code in order to make it unit-testable if PowerMock is not used.
+ * Note that there's no need to refactor the class if PowerMock had been used.
+ */
+public class SampleServiceWithoutPowerMockImpl implements SampleService {
+
+ private final PersonService personService;
+
+ private final EventService eventService;
+
+ /**
+ * Creates a new instance of the SampleServiceImpl with the following
+ * collaborators.
+ *
+ * @param personService
+ * The person service to use.
+ * @param eventService
+ * The event service to use.
+ */
+ public SampleServiceWithoutPowerMockImpl(PersonService personService, EventService eventService) {
+ this.personService = personService;
+ this.eventService = eventService;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean createPerson(String firstName, String lastName) {
+ BusinessMessages messages = getNewBusinessMessagesInstance();
+ Person person = null;
+ try {
+ person = new Person(firstName, lastName);
+ } catch (IllegalArgumentException e) {
+ throw new SampleServiceException(e.getMessage(), e);
+ }
+
+ personService.create(person, messages);
+
+ final boolean hasErrors = messages.hasErrors();
+ if (hasErrors) {
+ eventService.sendErrorEvent(person, messages);
+ }
+
+ return !hasErrors;
+ }
+
+ /**
+ * In order to test this class without PowerMock we need to create a new
+ * protected method whose only purpose is to create a new instance of a
+ * BusinessMessage. This means that we can utilize partial mocking to
+ * override this method in our test and have it return a mock.
+ *
+ * @return A new instance of a {@link BusinessMessages} object.
+ */
+ protected BusinessMessages getNewBusinessMessagesInstance() {
+ return new BusinessMessages();
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorld.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorld.java
new file mode 100644
index 0000000..c28a71e
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorld.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower;
+
+public class HelloWorld {
+ public String greet() {
+ return SimpleConfig.getGreeting() + " " + SimpleConfig.getTarget();
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/SimpleConfig.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/SimpleConfig.java
new file mode 100644
index 0000000..592caae
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/SimpleConfig.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower;
+
+import java.util.Properties;
+
+/**
+ * Important third party code that cannot be changed.
+ */
+public class SimpleConfig {
+
+ private static Properties PROPERTIES;
+
+ private static synchronized void initialize() {
+ if (PROPERTIES == null) {
+ PROPERTIES = new Properties();
+ try {
+ PROPERTIES.load(SimpleConfig.class.getClassLoader().getResourceAsStream("simpleConfig.properties"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public static String getGreeting() {
+ initialize();
+ return PROPERTIES.getProperty("greeting");
+ }
+
+ public static String getTarget() {
+ initialize();
+ return PROPERTIES.getProperty("target");
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/ConfigWrapper.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/ConfigWrapper.java
new file mode 100644
index 0000000..9611db2
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/ConfigWrapper.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.hellopower.SimpleConfig;
+
+/**
+ * Encapsulate the use of the third party code in our own code that we can mock.
+ */
+public class ConfigWrapper {
+ public String getTarget() {
+ return SimpleConfig.getTarget();
+ }
+
+ public String getGreeting() {
+ return SimpleConfig.getGreeting();
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorld.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorld.java
new file mode 100644
index 0000000..0df8b24
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorld.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower.withoutpowermock;
+
+/**
+ * Use our own code instead of the third party code.
+ */
+public class HelloWorld {
+ private ConfigWrapper config;
+
+ public HelloWorld(ConfigWrapper config) {
+ this.config = config;
+ }
+
+ public String greet() {
+ return config.getGreeting() + " " + config.getTarget();
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/ProviderDao.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/ProviderDao.java
new file mode 100644
index 0000000..5a18825
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/ProviderDao.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.dao;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl.ServiceArtifact;
+
+import java.util.Set;
+
+public interface ProviderDao {
+
+ /**
+ * @return A set of all available service producers.
+ */
+ Set<ServiceArtifact> getAllServiceProducers();
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/Connection.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/Connection.java
new file mode 100644
index 0000000..3acdc45
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/Connection.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.dao.domain;
+
+public interface Connection {
+
+ void disconnect();
+
+ void send(byte[] data);
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ConnectionImpl.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ConnectionImpl.java
new file mode 100644
index 0000000..fc9b1a6
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ConnectionImpl.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.Connection;
+
+public class ConnectionImpl implements Connection {
+
+ @Override
+ public void disconnect() {
+ System.out.println("Disconnecting...");
+ }
+
+ @Override
+ public void send(byte[] data) {
+ System.out.println("Sending data of " + data.length + " bytes.");
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ServiceArtifact.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ServiceArtifact.java
new file mode 100644
index 0000000..c86a033
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/dao/domain/impl/ServiceArtifact.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.Connection;
+import demo.org.powermock.examples.tutorial.partialmocking.domain.DataProducer;
+
+public class ServiceArtifact {
+
+ private final int id;
+
+ private final String name;
+
+ private final DataProducer[] dataProducers;
+
+ public ServiceArtifact(int id, String name, DataProducer... dataProducers) {
+ this.id = id;
+ this.name = name;
+ this.dataProducers = dataProducers;
+ }
+
+ public DataProducer[] getDataProducers() {
+ return dataProducers;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Connection connectToService() {
+ return new ConnectionImpl();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final ServiceArtifact other = (ServiceArtifact) obj;
+ if (id != other.id)
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/DataProducer.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/DataProducer.java
new file mode 100644
index 0000000..b7a21d3
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/DataProducer.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.domain;
+
+public class DataProducer extends ProviderArtifact {
+
+ public DataProducer(int id, String name) {
+ super(id, name);
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ProviderArtifact.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ProviderArtifact.java
new file mode 100644
index 0000000..22f9161
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ProviderArtifact.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.domain;
+
+public abstract class ProviderArtifact {
+
+ private final int id;
+
+ private final String name;
+
+ public ProviderArtifact(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final ProviderArtifact other = (ProviderArtifact) obj;
+ if (id != other.id)
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ return true;
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ServiceProducer.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ServiceProducer.java
new file mode 100644
index 0000000..8e1b7eb
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/domain/ServiceProducer.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.domain;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ServiceProducer extends ProviderArtifact {
+ private final Set<DataProducer> dataProducingArtifacts;
+
+ public ServiceProducer(int id, String name, DataProducer... dataProducingArtifacts) {
+ super(id, name);
+ this.dataProducingArtifacts = new HashSet<DataProducer>();
+ for (DataProducer dataProducingArtifact : dataProducingArtifacts) {
+ this.dataProducingArtifacts.add(dataProducingArtifact);
+ }
+ }
+
+ public Set<DataProducer> getDataProducers() {
+ return Collections.unmodifiableSet(dataProducingArtifacts);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((dataProducingArtifacts == null) ? 0 : dataProducingArtifacts.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!super.equals(obj))
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final ServiceProducer other = (ServiceProducer) obj;
+ if (dataProducingArtifacts == null) {
+ if (other.dataProducingArtifacts != null)
+ return false;
+ } else if (!dataProducingArtifacts.equals(other.dataProducingArtifacts))
+ return false;
+ return true;
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/ProviderService.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/ProviderService.java
new file mode 100644
index 0000000..6825dc4
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/ProviderService.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service;
+
+import demo.org.powermock.examples.tutorial.partialmocking.domain.ServiceProducer;
+
+import java.util.Set;
+
+/**
+ * A simple interface that manages persons.
+ */
+public interface ProviderService {
+
+ /**
+ * Get all service provider.
+ *
+ * @return All service provider artifacts currently available or an empty
+ * set if no service providers are available.
+ */
+ Set<ServiceProducer> getAllServiceProviders();
+
+ /**
+ * Get a service provider.
+ *
+ * @param id
+ * The id of the service provider to get.
+ * @return The service artifact that represents the service provider or
+ * <code>null</code> if no Service Producer was found with that
+ * id.
+ */
+ ServiceProducer getServiceProvider(int id);
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImpl.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImpl.java
new file mode 100644
index 0000000..744df5b
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImpl.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service.impl;
+
+import demo.org.powermock.examples.tutorial.common.annotation.Inject;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.ProviderDao;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl.ServiceArtifact;
+import demo.org.powermock.examples.tutorial.partialmocking.domain.ServiceProducer;
+import demo.org.powermock.examples.tutorial.partialmocking.service.ProviderService;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A simple implementation of the providers service. This is the class that's
+ * going to be tested using PowerMock. The main reason for the test is to
+ * demonstrate how to use PowerMock to set internal state (i.e. setting the
+ * <code>providerDao</code> field without setters), partial mocking and
+ * expectations of private methods.
+ */
+public class ProviderServiceImpl implements ProviderService {
+
+ @Inject
+ private ProviderDao providerDao;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ServiceProducer> getAllServiceProviders() {
+ final Set<ServiceProducer> serviceProducers = getAllServiceProducers();
+ if (serviceProducers == null) {
+ return Collections.emptySet();
+ }
+ return serviceProducers;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ServiceProducer getServiceProvider(int id) {
+ Set<ServiceProducer> allServiceProducers = getAllServiceProducers();
+ for (ServiceProducer serviceProducer : allServiceProducers) {
+ if (serviceProducer.getId() == id) {
+ return serviceProducer;
+ }
+ }
+ return null;
+ }
+
+ private Set<ServiceProducer> getAllServiceProducers() {
+ Set<ServiceArtifact> serviceArtifacts = providerDao.getAllServiceProducers();
+ Set<ServiceProducer> serviceProducers = new HashSet<ServiceProducer>();
+
+ for (ServiceArtifact serviceArtifact : serviceArtifacts) {
+ serviceProducers.add(new ServiceProducer(serviceArtifact.getId(), serviceArtifact.getName(), serviceArtifact.getDataProducers()));
+ }
+ return serviceProducers;
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImpl.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImpl.java
new file mode 100644
index 0000000..35e0920
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImpl.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.common.annotation.Inject;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.ProviderDao;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl.ServiceArtifact;
+import demo.org.powermock.examples.tutorial.partialmocking.domain.ServiceProducer;
+import demo.org.powermock.examples.tutorial.partialmocking.service.ProviderService;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * We've slightly refactored the <code>ProviderService</code> to make the
+ * class easier to test without PowerMock. What we've done is to use constructor
+ * injection for the <code>providerDao</code> instead of field injection.
+ * We've also refactored the {@link #getAllServiceProducers()} method to be
+ * protected instead of private.
+ * <p>
+ * Note no refactoring is actually needed to test this method without PowerMock,
+ * everything PowerMock does in this case can be done manually using reflection.
+ * It's however common to do this refactoring instead of using too much
+ * reflection in the test code.
+ *
+ */
+public class ProviderServiceWithoutPowerMockImpl implements ProviderService {
+
+ private ProviderDao providerDao;
+
+ @Inject
+ public ProviderServiceWithoutPowerMockImpl(ProviderDao providerDao) {
+ if (providerDao == null) {
+ throw new IllegalArgumentException("providerDao cannot be null");
+ }
+
+ this.providerDao = providerDao;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Set<ServiceProducer> getAllServiceProviders() {
+ final Set<ServiceProducer> serviceProducers = getAllServiceProducers();
+ if (serviceProducers == null) {
+ return Collections.emptySet();
+ }
+ return serviceProducers;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ServiceProducer getServiceProvider(int id) {
+ Set<ServiceProducer> allServiceProducers = getAllServiceProducers();
+ for (ServiceProducer serviceProducer : allServiceProducers) {
+ if (serviceProducer.getId() == id) {
+ return serviceProducer;
+ }
+ }
+ return null;
+ }
+
+ protected Set<ServiceProducer> getAllServiceProducers() {
+ Set<ServiceArtifact> serviceArtifacts = providerDao.getAllServiceProducers();
+ Set<ServiceProducer> serviceProducers = new HashSet<ServiceProducer>();
+
+ for (ServiceArtifact serviceArtifact : serviceArtifacts) {
+ serviceProducers.add(new ServiceProducer(serviceArtifact.getId(), serviceArtifact.getName(), serviceArtifact.getDataProducers()));
+ }
+ return serviceProducers;
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/IServiceRegistrator.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/IServiceRegistrator.java
new file mode 100644
index 0000000..2f2063b
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/IServiceRegistrator.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking;
+
+/**
+ * An interface to be implemented by services that performs service
+ * registrations.
+ */
+public interface IServiceRegistrator {
+ /**
+ * Registers a service to the service framework.
+ *
+ * @param name
+ * The name of the service the register.
+ * @param serviceImplementation
+ * The implementation of the service.
+ * @return An id of the service that got registered. Should be used when
+ * unregistering the service.
+ */
+ long registerService(String name, Object serviceImplementation);
+
+ /**
+ * Unregisters a service from the service framework.
+ *
+ * @param id
+ * The id of the service that should be removed. The id was
+ * generated by {@link #registerService(String, Object)}.
+ *
+ * @throws IllegalStateException
+ * If this <code>ServiceRegistration</code> object has already
+ * been unregistered.
+ */
+ void unregisterService(long id);
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/IdGenerator.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/IdGenerator.java
new file mode 100644
index 0000000..3e7ca00
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/IdGenerator.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl;
+
+/**
+ * The purpose of the IdGenerator is to generate ID's based on the system time.
+ */
+public class IdGenerator {
+
+ /**
+ * @return A new ID based on the current time.
+ */
+ public static long generateNewId() {
+ return System.currentTimeMillis();
+ }
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistrator.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistrator.java
new file mode 100644
index 0000000..9ff82e7
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistrator.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl;
+
+import demo.org.powermock.examples.tutorial.common.annotation.Inject;
+import demo.org.powermock.examples.tutorial.staticmocking.IServiceRegistrator;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.BundleContext;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.ServiceRegistration;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * An "OSGi"-ish implementation of the {@link IServiceRegistrator} interface.
+ * The test for this class demonstrates static mocking as well as getting and
+ * setting internal state.
+ *
+ */
+public class ServiceRegistrator implements IServiceRegistrator {
+
+ @Inject
+ private BundleContext bundleContext;
+
+ /**
+ * Holds all services registrations that has been registered by this service
+ * registrator.
+ */
+ private final Map<Long, ServiceRegistration> serviceRegistrations;
+
+ /**
+ * Default constructor, initializes internal state.
+ */
+ public ServiceRegistrator() {
+ serviceRegistrations = new ConcurrentHashMap<Long, ServiceRegistration>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long registerService(String name, Object serviceImplementation) {
+ ServiceRegistration registerService = bundleContext.registerService(name, serviceImplementation, null);
+ final long id = IdGenerator.generateNewId();
+ serviceRegistrations.put(id, registerService);
+ return id;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void unregisterService(long id) {
+ final ServiceRegistration registration = serviceRegistrations.remove(id);
+ if (registration == null) {
+ throw new IllegalStateException("Registration with id " + id + " has already been removed or has never been registered");
+ }
+ registration.unregister();
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorWithoutPowerMock.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorWithoutPowerMock.java
new file mode 100644
index 0000000..ab9d4b7
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorWithoutPowerMock.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.common.annotation.Inject;
+import demo.org.powermock.examples.tutorial.staticmocking.IServiceRegistrator;
+import demo.org.powermock.examples.tutorial.staticmocking.impl.IdGenerator;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.BundleContext;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.ServiceRegistration;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This refactored implementation demonstrate how one could test the
+ * <code>ServiceRegistrator</code> class without using PowerMock.
+ *
+ */
+public class ServiceRegistratorWithoutPowerMock implements IServiceRegistrator {
+
+ @Inject
+ private BundleContext bundleContext;
+
+ /**
+ * Holds all services registrations that has been registered by this service
+ * registrator.
+ */
+ private final Map<Long, ServiceRegistration> serviceRegistrations;
+
+ /**
+ * Default constructor, initializes internal state.
+ */
+ public ServiceRegistratorWithoutPowerMock() {
+ serviceRegistrations = new ConcurrentHashMap<Long, ServiceRegistration>();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public long registerService(String name, Object serviceImplementation) {
+ ServiceRegistration registerService = bundleContext.registerService(name, serviceImplementation, null);
+ final long id = generateId();
+ serviceRegistrations.put(id, registerService);
+ return id;
+ }
+
+ /**
+ * @return A new id
+ */
+ protected long generateId() {
+ return IdGenerator.generateNewId();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void unregisterService(long id) {
+ final ServiceRegistration registration = serviceRegistrations.remove(id);
+ if (registration == null) {
+ throw new IllegalStateException("Registration with id " + id + " has already been removed or has never been registered");
+ }
+ registration.unregister();
+ }
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/BundleContext.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/BundleContext.java
new file mode 100644
index 0000000..2332e6d
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/BundleContext.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.osgi;
+
+/**
+ * Copied method declaration from the OSGi BundleContext interface. It's just
+ * here for demonstration purposes.
+ */
+public interface BundleContext {
+
+ ServiceRegistration registerService(String name, Object serviceImplementation, String filter);
+
+}
diff --git a/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/ServiceRegistration.java b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/ServiceRegistration.java
new file mode 100644
index 0000000..eb50028
--- /dev/null
+++ b/examples/tutorial/src/main/java/demo/org/powermock/examples/tutorial/staticmocking/osgi/ServiceRegistration.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.osgi;
+
+/**
+ * Copied method declaration from the OSGi ServiceRegistration interface. It's
+ * just here for demonstration purposes.
+ */
+public interface ServiceRegistration {
+
+ void unregister();
+
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest.java
new file mode 100644
index 0000000..776c70a
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.impl;
+
+import demo.org.powermock.examples.tutorial.domainmocking.EventService;
+import demo.org.powermock.examples.tutorial.domainmocking.PersonService;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.SampleServiceException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { SampleServiceImpl.class, BusinessMessages.class, Person.class })
+public class SampleServiceImplTest {
+
+ private SampleServiceImpl tested;
+ private PersonService personServiceMock;
+ private EventService eventService;
+
+ @Before
+ public void setUp() {
+ personServiceMock = createMock(PersonService.class);
+ eventService = createMock(EventService.class);
+
+ tested = new SampleServiceImpl(personServiceMock, eventService);
+ }
+
+ @After
+ public void tearDown() {
+ personServiceMock = null;
+ eventService = null;
+ tested = null;
+ }
+
+ @Test
+ public void testCreatePerson() throws Exception {
+ // Mock the creation of person
+ final String firstName = "firstName";
+ final String lastName = "lastName";
+ Person personMock = createMockAndExpectNew(Person.class, firstName, lastName);
+
+ // Mock the creation of BusinessMessages
+ BusinessMessages businessMessagesMock = createMockAndExpectNew(BusinessMessages.class);
+
+ personServiceMock.create(personMock, businessMessagesMock);
+ expectLastCall().times(1);
+
+ expect(businessMessagesMock.hasErrors()).andReturn(false);
+
+ replayAll();
+
+ assertTrue(tested.createPerson(firstName, lastName));
+
+ verifyAll();
+ }
+
+ @Test
+ public void testCreatePerson_error() throws Exception {
+ // Mock the creation of person
+ final String firstName = "firstName";
+ final String lastName = "lastName";
+ Person personMock = createMockAndExpectNew(Person.class, firstName, lastName);
+
+ // Mock the creation of BusinessMessages
+ BusinessMessages businessMessagesMock = createMockAndExpectNew(BusinessMessages.class);
+
+ personServiceMock.create(personMock, businessMessagesMock);
+ expectLastCall().times(1);
+
+ expect(businessMessagesMock.hasErrors()).andReturn(true);
+
+ eventService.sendErrorEvent(personMock, businessMessagesMock);
+ expectLastCall().times(1);
+
+ replayAll();
+
+ assertFalse(tested.createPerson(firstName, lastName));
+
+ verifyAll();
+ }
+
+ @Test(expected = SampleServiceException.class)
+ public void testCreatePerson_illegalName() throws Exception {
+ // Mock the creation of person
+ final String firstName = "firstName";
+ final String lastName = "lastName";
+ expectNew(Person.class, firstName, lastName).andThrow(new IllegalArgumentException("Illegal name"));
+
+ replayAll();
+
+ tested.createPerson(firstName, lastName);
+
+ verifyAll();
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImplTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImplTest.java
new file mode 100644
index 0000000..9f91938
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/domainmocking/impl/withoutpowermock/SampleServiceWithoutPowerMockImplTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.domainmocking.EventService;
+import demo.org.powermock.examples.tutorial.domainmocking.PersonService;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.BusinessMessages;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.Person;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.SampleServiceException;
+import org.easymock.ConstructorArgs;
+import org.easymock.EasyMock;
+import org.easymock.internal.matchers.Equals;
+import org.easymock.internal.matchers.Same;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.createMock;
+
+/**
+ * This test demonstrates how to test the refactored SampleService without
+ * PowerMock.
+ */
+public class SampleServiceWithoutPowerMockImplTest {
+
+ private SampleServiceWithoutPowerMockImpl tested;
+ private BusinessMessages businessMessagesMock;
+ private PersonService personServiceMock;
+ private EventService eventServiceMock;
+
+ private ConstructorArgs constructorArgs;
+
+ @SuppressWarnings("deprecation")
+ @Before
+ public void setUp() throws Exception {
+ businessMessagesMock = EasyMock.createMock(BusinessMessages.class);
+ personServiceMock = EasyMock.createMock(PersonService.class);
+ eventServiceMock = EasyMock.createMock(EventService.class);
+ constructorArgs = new ConstructorArgs(SampleServiceWithoutPowerMockImpl.class.getConstructor(PersonService.class, EventService.class),
+ personServiceMock, eventServiceMock);
+ tested = createMock(SampleServiceWithoutPowerMockImpl.class, constructorArgs);
+ }
+
+ @After
+ public void tearDown() {
+ businessMessagesMock = null;
+ personServiceMock = null;
+ eventServiceMock = null;
+ constructorArgs = null;
+ tested = null;
+ }
+
+ protected void replayAll() {
+ replay(businessMessagesMock, personServiceMock, eventServiceMock, tested);
+ }
+
+ protected void verifyAll() {
+ verify(businessMessagesMock, personServiceMock, eventServiceMock, tested);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testCreatePerson() throws Exception {
+ final String firstName = "firstName";
+ final String lastName = "lastName";
+
+ Method getNewBusinessMessagesInstanceMethod = SampleServiceWithoutPowerMockImpl.class.getDeclaredMethod("getNewBusinessMessagesInstance");
+ tested = createMock(SampleServiceWithoutPowerMockImpl.class, constructorArgs, getNewBusinessMessagesInstanceMethod);
+
+ expect(tested.getNewBusinessMessagesInstance()).andReturn(businessMessagesMock);
+
+ personServiceMock.create(eq(new Person(firstName, lastName)), same(businessMessagesMock));
+ expectLastCall().once();
+
+ expect(businessMessagesMock.hasErrors()).andReturn(false);
+
+ replayAll();
+
+ assertTrue(tested.createPerson(firstName, lastName));
+
+ verifyAll();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testCreatePerson_error() throws Exception {
+ final String firstName = "firstName";
+ final String lastName = "lastName";
+
+ Method getNewBusinessMessagesInstanceMethod = SampleServiceWithoutPowerMockImpl.class.getDeclaredMethod("getNewBusinessMessagesInstance");
+ tested = createMock(SampleServiceWithoutPowerMockImpl.class, constructorArgs, getNewBusinessMessagesInstanceMethod);
+
+ expect(tested.getNewBusinessMessagesInstance()).andReturn(businessMessagesMock);
+
+ final Person person = new Person(firstName, lastName);
+ personServiceMock.create(eq(person), same(businessMessagesMock));
+ expectLastCall().once();
+
+ expect(businessMessagesMock.hasErrors()).andReturn(true);
+
+ eventServiceMock.sendErrorEvent(person, businessMessagesMock);
+ expectLastCall().once();
+
+ replayAll();
+
+ assertFalse(tested.createPerson(firstName, lastName));
+
+ verifyAll();
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test(expected = SampleServiceException.class)
+ public void testCreatePerson_illegalName() throws Exception {
+ final String firstName = null;
+ final String lastName = "lastName";
+
+ Method getNewBusinessMessagesInstanceMethod = SampleServiceWithoutPowerMockImpl.class.getDeclaredMethod("getNewBusinessMessagesInstance");
+ tested = createMock(SampleServiceWithoutPowerMockImpl.class, constructorArgs, getNewBusinessMessagesInstanceMethod);
+
+ expect(tested.getNewBusinessMessagesInstance()).andReturn(businessMessagesMock);
+
+ replayAll();
+
+ tested.createPerson(firstName, lastName);
+
+ verifyAll();
+ }
+
+ private static <T> T eq(T object) {
+ reportMatcher(new Equals(object));
+ return object;
+ }
+
+ private static <T> T same(T object) {
+ reportMatcher(new Same(object));
+ return object;
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest.java
new file mode 100644
index 0000000..ffdbd1e
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at PrepareForTest(SimpleConfig.class)
+ at RunWith(PowerMockRunner.class)
+public class HelloWorldTest {
+
+ @Test
+ public void testGreeting() throws Exception {
+ mockStatic(SimpleConfig.class);
+ expect(SimpleConfig.getGreeting()).andReturn("Hello");
+ expect(SimpleConfig.getTarget()).andReturn("world");
+
+ replayAll();
+
+ assertEquals("Hello world", new HelloWorld().greet());
+
+ verifyAll();
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorldTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorldTest.java
new file mode 100644
index 0000000..8530449
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/hellopower/withoutpowermock/HelloWorldTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower.withoutpowermock;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+public class HelloWorldTest {
+
+ @Test
+ public void testGreeting() {
+ ConfigWrapper config = EasyMock.createMock(ConfigWrapper.class);
+ expect(config.getGreeting()).andReturn("Hello");
+ expect(config.getTarget()).andReturn("world");
+
+ replay(config);
+
+ assertEquals("Hello world", new HelloWorld(config).greet());
+
+ verify(config);
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest.java
new file mode 100644
index 0000000..129e00e
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service.impl;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.ProviderDao;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl.ServiceArtifact;
+import demo.org.powermock.examples.tutorial.partialmocking.domain.ServiceProducer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.reflect.Whitebox.invokeMethod;
+import static org.powermock.reflect.Whitebox.setInternalState;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ProviderServiceImpl.class)
+public class ProviderServiceImplTest {
+
+ private ProviderServiceImpl tested;
+ private ProviderDao providerDaoMock;
+
+ @Before
+ public void setUp() {
+ tested = new ProviderServiceImpl();
+ providerDaoMock = createMock(ProviderDao.class);
+
+ setInternalState(tested, providerDaoMock);
+ }
+
+ @After
+ public void tearDown() {
+ tested = null;
+ providerDaoMock = null;
+ }
+
+ @Test
+ public void testGetAllServiceProviders() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final Set<ServiceProducer> expectedServiceProducers = new HashSet<ServiceProducer>();
+ expectedServiceProducers.add(new ServiceProducer(1, "mock name"));
+
+ tested = createPartialMock(ProviderServiceImpl.class, methodNameToMock);
+
+ expectPrivate(tested, methodNameToMock).andReturn(expectedServiceProducers);
+
+ replayAll();
+
+ Set<ServiceProducer> actualServiceProviders = tested.getAllServiceProviders();
+
+ verifyAll();
+
+ assertSame(expectedServiceProducers, actualServiceProviders);
+ }
+
+ @Test
+ public void testGetAllServiceProviders_noServiceProvidersFound() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final Set<ServiceProducer> expectedServiceProducers = new HashSet<ServiceProducer>();
+
+ tested = createPartialMock(ProviderServiceImpl.class, methodNameToMock);
+
+ expectPrivate(tested, methodNameToMock).andReturn(null);
+
+ replayAll();
+
+ Set<ServiceProducer> actualServiceProviders = tested.getAllServiceProviders();
+
+ verifyAll();
+
+ assertNotSame(expectedServiceProducers, actualServiceProviders);
+ assertEquals(expectedServiceProducers, actualServiceProviders);
+ }
+
+ @Test
+ public void testServiceProvider_found() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final int expectedServiceProducerId = 1;
+ final ServiceProducer expected = new ServiceProducer(expectedServiceProducerId, "mock name");
+
+ final Set<ServiceProducer> serviceProducers = new HashSet<ServiceProducer>();
+ serviceProducers.add(expected);
+
+ tested = createPartialMock(ProviderServiceImpl.class, methodNameToMock);
+
+ expectPrivate(tested, methodNameToMock).andReturn(serviceProducers);
+
+ replayAll();
+
+ ServiceProducer actual = tested.getServiceProvider(expectedServiceProducerId);
+
+ verifyAll();
+
+ assertSame(expected, actual);
+ }
+
+ @Test
+ public void testServiceProvider_notFound() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final int expectedServiceProducerId = 1;
+
+ tested = createPartialMock(ProviderServiceImpl.class, methodNameToMock);
+
+ expectPrivate(tested, methodNameToMock).andReturn(new HashSet<ServiceProducer>());
+
+ replayAll();
+
+ assertNull(tested.getServiceProvider(expectedServiceProducerId));
+
+ verifyAll();
+
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void getAllServiceProducers() throws Exception {
+ final String expectedName = "mock name";
+ final int expectedId = 1;
+
+ final Set<ServiceArtifact> serviceArtifacts = new HashSet<ServiceArtifact>();
+ serviceArtifacts.add(new ServiceArtifact(expectedId, expectedName));
+
+ expect(providerDaoMock.getAllServiceProducers()).andReturn(serviceArtifacts);
+
+ replayAll();
+
+ Set<ServiceProducer> serviceProducers = (Set<ServiceProducer>) invokeMethod(tested, "getAllServiceProducers");
+
+ verifyAll();
+
+ assertEquals(1, serviceProducers.size());
+ assertTrue(serviceProducers.contains(new ServiceProducer(expectedId, expectedName)));
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void getAllServiceProducers_empty() throws Exception {
+ expect(providerDaoMock.getAllServiceProducers()).andReturn(new HashSet<ServiceArtifact>());
+
+ replayAll();
+
+ Set<ServiceProducer> actual = (Set<ServiceProducer>) invokeMethod(tested, "getAllServiceProducers");
+
+ verifyAll();
+
+ assertTrue(actual.isEmpty());
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImplTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImplTest.java
new file mode 100644
index 0000000..4d3a70e
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/withoutpowermock/ProviderServiceWithoutPowerMockImplTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.ProviderDao;
+import demo.org.powermock.examples.tutorial.partialmocking.dao.domain.impl.ServiceArtifact;
+import demo.org.powermock.examples.tutorial.partialmocking.domain.ServiceProducer;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.api.easymock.PowerMock;
+
+import java.lang.reflect.Method;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+
+/**
+ * Unit test for the {@link ProviderServiceWithoutPowerMockImpl} class.
+ */
+public class ProviderServiceWithoutPowerMockImplTest {
+
+ private ProviderServiceWithoutPowerMockImpl tested;
+ private ProviderDao providerDaoMock;
+
+ @Before
+ public void setUp() {
+ providerDaoMock = createMock(ProviderDao.class);
+ tested = new ProviderServiceWithoutPowerMockImpl(providerDaoMock);
+ }
+
+ @After
+ public void tearDown() {
+ tested = null;
+ providerDaoMock = null;
+ }
+
+ @Test
+ public void testGetAllServiceProviders() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final Set<ServiceProducer> expectedServiceProducers = new HashSet<ServiceProducer>();
+ expectedServiceProducers.add(new ServiceProducer(1, "mock name"));
+
+ createPartialMock(methodNameToMock);
+
+ expect(tested.getAllServiceProviders()).andReturn(expectedServiceProducers);
+
+ replayAll(tested);
+
+ Set<ServiceProducer> actualServiceProviders = tested.getAllServiceProviders();
+
+ verifyAll(tested);
+
+ assertSame(expectedServiceProducers, actualServiceProviders);
+ }
+
+ @Test
+ public void testGetAllServiceProviders_noServiceProvidersFound() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final Set<ServiceProducer> expectedServiceProducers = new HashSet<ServiceProducer>();
+
+ createPartialMock(methodNameToMock);
+
+ expect(tested.getAllServiceProviders()).andReturn(null);
+
+ replayAll(tested);
+
+ Set<ServiceProducer> actualServiceProviders = tested.getAllServiceProviders();
+
+ verifyAll(tested);
+
+ assertNotSame(expectedServiceProducers, actualServiceProviders);
+ assertEquals(expectedServiceProducers, actualServiceProviders);
+ }
+
+ @Test
+ public void testServiceProvider_found() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final int expectedServiceProducerId = 1;
+ final ServiceProducer expected = new ServiceProducer(expectedServiceProducerId, "mock name");
+
+ final Set<ServiceProducer> serviceProducers = new HashSet<ServiceProducer>();
+ serviceProducers.add(expected);
+
+ createPartialMock(methodNameToMock);
+
+ expect(tested.getAllServiceProducers()).andReturn(serviceProducers);
+
+ replayAll(tested);
+
+ ServiceProducer actual = tested.getServiceProvider(expectedServiceProducerId);
+
+ verifyAll(tested);
+
+ assertSame(expected, actual);
+ }
+
+ @Test
+ public void testServiceProvider_notFound() throws Exception {
+ final String methodNameToMock = "getAllServiceProducers";
+ final int expectedServiceProducerId = 1;
+
+ createPartialMock(methodNameToMock);
+
+ expect(tested.getAllServiceProducers()).andReturn(new HashSet<ServiceProducer>());
+
+ replayAll(tested);
+
+ assertNull(tested.getServiceProvider(expectedServiceProducerId));
+
+ verifyAll(tested);
+
+ }
+
+ @Test
+ public void getAllServiceProducers() throws Exception {
+ final String expectedName = "mock name";
+ final int expectedId = 1;
+
+ final Set<ServiceArtifact> serviceArtifacts = new HashSet<ServiceArtifact>();
+ serviceArtifacts.add(new ServiceArtifact(expectedId, expectedName));
+
+ expect(providerDaoMock.getAllServiceProducers()).andReturn(serviceArtifacts);
+
+ replayAll();
+
+ Set<ServiceProducer> serviceProducers = tested.getAllServiceProducers();
+
+ verifyAll();
+
+ assertEquals(1, serviceProducers.size());
+ assertTrue(serviceProducers.contains(new ServiceProducer(expectedId, expectedName)));
+ }
+
+ @Test
+ public void getAllServiceProducers_empty() throws Exception {
+ expect(providerDaoMock.getAllServiceProducers()).andReturn(new HashSet<ServiceArtifact>());
+
+ replayAll();
+
+ Set<ServiceProducer> actual = tested.getAllServiceProducers();
+
+ verifyAll();
+
+ assertTrue(actual.isEmpty());
+ }
+
+ protected void replayAll(Object... additionalMocks) {
+ replay(providerDaoMock);
+ if (additionalMocks != null) {
+ replay(additionalMocks);
+ }
+ }
+
+ protected void verifyAll(Object... additionalMocks) {
+ verify(providerDaoMock);
+ if (additionalMocks != null) {
+ verify(additionalMocks);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void createPartialMock(final String methodNameToMock) throws NoSuchMethodException {
+ Method getAllServiceProducersMethod = ProviderServiceWithoutPowerMockImpl.class.getDeclaredMethod(methodNameToMock);
+ tested = PowerMock.createMock(ProviderServiceWithoutPowerMockImpl.class, getAllServiceProducersMethod);
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest.java
new file mode 100644
index 0000000..38eaba9
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl;
+
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.BundleContext;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.ServiceRegistration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.reflect.Whitebox.getInternalState;
+import static org.powermock.reflect.Whitebox.setInternalState;
+
+/**
+ * Unit test for the {@link ServiceRegistrator} class.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(IdGenerator.class)
+public class ServiceRegistratorTest {
+ private ServiceRegistrator tested;
+
+ private BundleContext bundleContextMock;
+
+ private ServiceRegistration serviceRegistrationMock;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Before
+ public void setUp() {
+ tested = new ServiceRegistrator();
+ bundleContextMock = createMock(BundleContext.class);
+ serviceRegistrationMock = createMock(ServiceRegistration.class);
+ mockStatic(IdGenerator.class);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @After
+ public void tearDown() {
+ tested = null;
+ bundleContextMock = null;
+ serviceRegistrationMock = null;
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#registerService(String, Object)}
+ * method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testRegisterService() throws Exception {
+ final String name = "a name";
+ final Object object = new Object();
+ final long expectedId = 42;
+
+ setInternalState(tested, bundleContextMock);
+
+ expect(bundleContextMock.registerService(name, object, null)).andReturn(serviceRegistrationMock);
+ expect(IdGenerator.generateNewId()).andReturn(expectedId);
+
+ replayAll();
+
+ final long actualId = tested.registerService(name, object);
+
+ verifyAll();
+
+ Map<Long, ServiceRegistration> map = getInternalState(tested, Map.class);
+
+ assertEquals(1, map.size());
+ assertTrue("The id " + actualId + " was not found in the mServiceRegistrations map.", map.containsKey(actualId));
+ assertTrue("The service " + serviceRegistrationMock + " was not found in the mServiceRegistrations map.", map
+ .containsValue(serviceRegistrationMock));
+ assertNotNull(map.get(expectedId));
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#unregisterService(long)} method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService() throws Exception {
+ Map<Long, ServiceRegistration> map = new HashMap<Long, ServiceRegistration>();
+ final long id = 1L;
+ map.put(id, serviceRegistrationMock);
+
+ setInternalState(tested, map);
+
+ serviceRegistrationMock.unregister();
+ expectLastCall().times(1);
+
+ replayAll();
+
+ tested.unregisterService(id);
+
+ verifyAll();
+
+ assertTrue("Map should be empty", map.isEmpty());
+
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#unregisterService(long)} method
+ * when the ID doesn't exist.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService_idDoesntExist() throws Exception {
+ Map<Long, ServiceRegistration> map = new HashMap<Long, ServiceRegistration>();
+ final long id = 1L;
+
+ setInternalState(tested, map);
+
+ replayAll();
+
+ try {
+ tested.unregisterService(id);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ assertEquals("Registration with id " + id + " has already been removed or has never been registered", e.getMessage());
+ }
+
+ verifyAll();
+
+ assertTrue("Map should be empty", map.isEmpty());
+
+ }
+}
diff --git a/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorTest.java b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorTest.java
new file mode 100644
index 0000000..d4b06bf
--- /dev/null
+++ b/examples/tutorial/src/solution/java/demo/org/powermock/examples/tutorial/staticmocking/impl/withoutpowermock/ServiceRegistratorTest.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl.withoutpowermock;
+
+import demo.org.powermock.examples.tutorial.staticmocking.impl.ServiceRegistrator;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.BundleContext;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.ServiceRegistration;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+
+/**
+ * Unit test for the {@link ServiceRegistrator} class.
+ */
+public class ServiceRegistratorTest {
+ private ServiceRegistratorWithoutPowerMock tested;
+
+ private BundleContext bundleContextMock;
+
+ private ServiceRegistration serviceRegistrationMock;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Before
+ public void setUp() {
+ tested = new ServiceRegistratorWithoutPowerMock();
+ bundleContextMock = EasyMock.createMock(BundleContext.class);
+ serviceRegistrationMock = EasyMock.createMock(ServiceRegistration.class);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @After
+ public void tearDown() {
+ tested = null;
+ bundleContextMock = null;
+ serviceRegistrationMock = null;
+ }
+
+ /**
+ * Replay all mocks.
+ */
+ protected void replayAll() {
+ replay(bundleContextMock);
+ replay(serviceRegistrationMock);
+ }
+
+ /**
+ * Verify all mocks.
+ */
+ protected void verifyAll() {
+ verify(bundleContextMock);
+ verify(serviceRegistrationMock);
+ }
+
+ /**
+ * Test for the
+ * {@link ServiceRegistratorWithoutPowerMock#registerService(String, Object)}
+ * method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testRegisterService() throws Exception {
+ final String name = "a name";
+ final Object object = new Object();
+ final long expectedId = 42;
+
+ Method generateIdMethod = ServiceRegistratorWithoutPowerMock.class.getDeclaredMethod("generateId");
+ tested = createMock(ServiceRegistratorWithoutPowerMock.class, generateIdMethod);
+
+ Field field = ServiceRegistratorWithoutPowerMock.class.getDeclaredField("bundleContext");
+ field.setAccessible(true);
+ field.set(tested, bundleContextMock);
+
+ Map<Long, ServiceRegistration> map = new HashMap<Long, ServiceRegistration>();
+ field = ServiceRegistratorWithoutPowerMock.class.getDeclaredField("serviceRegistrations");
+ field.setAccessible(true);
+ field.set(tested, map);
+
+ expect(bundleContextMock.registerService(name, object, null)).andReturn(serviceRegistrationMock);
+
+ expect(tested.generateId()).andReturn(expectedId);
+
+ replayAll();
+ replay(tested);
+
+ final long actualId = tested.registerService(name, object);
+
+ verifyAll();
+ verify(tested);
+
+ assertEquals(1, map.size());
+ final ServiceRegistration serviceRegistration = map.get(expectedId);
+ assertNotNull("The id " + actualId + " was not found in the mServiceRegistrations map.", serviceRegistration);
+ assertSame(serviceRegistration, serviceRegistrationMock);
+ }
+
+ /**
+ * Test for the
+ * {@link ServiceRegistratorWithoutPowerMock#unregisterService(long)}
+ * method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService() throws Exception {
+ Map<Long, ServiceRegistration> map = new HashMap<Long, ServiceRegistration>();
+ final long id = 1L;
+ map.put(id, serviceRegistrationMock);
+
+ Field field = tested.getClass().getDeclaredField("serviceRegistrations");
+ field.setAccessible(true);
+ field.set(tested, map);
+
+ serviceRegistrationMock.unregister();
+ expectLastCall().times(1);
+
+ replayAll();
+
+ tested.unregisterService(id);
+
+ verifyAll();
+
+ assertTrue("Map should be empty", map.isEmpty());
+
+ }
+
+ /**
+ * Test for the
+ * {@link ServiceRegistratorWithoutPowerMock#unregisterService(long)} method
+ * when the ID doesn't exist.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService_idDoesntExist() throws Exception {
+ Map<Long, ServiceRegistration> map = new HashMap<Long, ServiceRegistration>();
+ final long id = 1L;
+
+ Field field = tested.getClass().getDeclaredField("serviceRegistrations");
+ field.setAccessible(true);
+ field.set(tested, map);
+
+ replayAll();
+
+ try {
+ tested.unregisterService(id);
+ fail("Should throw IllegalStateException");
+ } catch (IllegalStateException e) {
+ assertEquals("Registration with id " + id + " has already been removed or has never been registered", e.getMessage());
+ }
+
+ verifyAll();
+
+ assertTrue("Map should be empty", map.isEmpty());
+
+ }
+}
diff --git a/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest_Tutorial.java b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest_Tutorial.java
new file mode 100644
index 0000000..c5c8950
--- /dev/null
+++ b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/domainmocking/impl/SampleServiceImplTest_Tutorial.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.domainmocking.impl;
+
+import demo.org.powermock.examples.tutorial.domainmocking.EventService;
+import demo.org.powermock.examples.tutorial.domainmocking.PersonService;
+import demo.org.powermock.examples.tutorial.domainmocking.domain.SampleServiceException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * The purpose of this test is to get 100% coverage of the
+ * {@link SampleServiceImpl} class without any code changes to that class. To
+ * achieve this you need learn how to mock instantiation of domain objects.
+ * <p>
+ * While doing this tutorial please refer to the documentation on how to mock
+ * construction of new objects at the PowerMock web site.
+ */
+// TODO Specify the PowerMock runner
+// TODO Specify which classes that must be prepared for test
+public class SampleServiceImplTest_Tutorial {
+
+ private SampleServiceImpl tested;
+ private PersonService personServiceMock;
+ private EventService eventService;
+
+ @Before
+ public void setUp() {
+ // TODO Create a mock object of the PersonService and Event service class
+ // TODO Create a new instance of SampleServiceImpl and pass in the created mock objects to the constructor
+ }
+
+ @After
+ public void tearDown() {
+ // TODO Set all references to null or use the FieldDefaulter test listener
+ }
+
+ @Test
+ public void testCreatePerson() throws Exception {
+ // TODO Create a mock object of the BusinessMessages class and mock the a construction of "new BusinessMessages" and instead return the mock
+ // TODO Create a mock object of the Person class and mock the a construction of "new Person" and instead return the mock
+ // TODO Expect the call to personService.createPerson(..)
+ // TODO Expect the call to businessMessages.hasErrors(..) and make it return false
+ // TODO Replay all mock objects used and also replay the classes whose constructions were mocked
+ // TODO Perform the actual test and assert that the result is false
+ // TODO Verify all mock objects used and also verify the classes whose constructions were mocked
+ }
+
+ @Test
+ public void testCreatePerson_error() throws Exception {
+ // TODO Create a mock object of the BusinessMessages class and mock the a construction of "new BusinessMessages" and instead return the mock
+ // TODO Create a mock object of the Person class and mock the a construction of "new Person" and instead return the mock
+ // TODO Expect the call to personService.createPerson(..)
+ // TODO Expect the call to businessMessages.hasErrors(..) and make it return true
+ // TODO Expect the all to eventService.sendErrorEvent(..)
+ // TODO Replay all mock objects used and also replay the classes whose constructions were mocked
+ // TODO Perform the actual test and assert that the result is false
+ // TODO Verify all mock objects used and also verify the classes whose constructions were mocked
+ }
+
+ @Test(expected = SampleServiceException.class)
+ public void testCreatePerson_illegalName() throws Exception {
+ // TODO Create a mock object of the Person class and mock the a construction of "new Person" but instead throw an IllegalArgumentException
+ // TODO Replay all mock objects used and also replay the classes whose constructions were mocked
+ // TODO Perform the actual test and assert that the result is false
+ // TODO Verify all mock objects used and also verify the classes whose constructions were mocked
+ }
+}
diff --git a/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest_Tutorial.java b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest_Tutorial.java
new file mode 100644
index 0000000..9308d96
--- /dev/null
+++ b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/hellopower/HelloWorldTest_Tutorial.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.hellopower;
+
+import org.junit.Test;
+
+/**
+ * The purpose of this test is to get 100% coverage of the {@link HelloWorld}
+ * class without any code changes to that class. To achieve this you need learn
+ * how to mock static methods.
+ * <p>
+ * While doing this tutorial please refer to the documentation on how to mock
+ * static methods at the PowerMock web site.
+ */
+// TODO Specify the PowerMock runner
+// TODO Specify which classes that must be prepared for test
+public class HelloWorldTest_Tutorial {
+
+ @Test
+ public void testGreeting() {
+ // TODO: mock the static methods of SimpleConfig
+ // TODO: Replay the behavior
+ // TODO: Perform the test of the greet method and assert that it returns the expected behavior
+ // TODO: Verify the behavior
+ }
+}
diff --git a/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest_Tutorial.java b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest_Tutorial.java
new file mode 100644
index 0000000..e89101d
--- /dev/null
+++ b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/partialmocking/service/impl/ProviderServiceImplTest_Tutorial.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.partialmocking.service.impl;
+
+import demo.org.powermock.examples.tutorial.partialmocking.dao.ProviderDao;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * The purpose of this test is to get 100% coverage of the
+ * {@link ProviderServiceImpl} class without any code changes to that class. To
+ * achieve this you need learn how to create partial mocks, modify internal
+ * state, invoke and expect private methods.
+ * <p>
+ * While doing this tutorial please refer to the documentation on how to expect
+ * private methods and bypass encapsulation at the PowerMock web site.
+ */
+// TODO Specify the PowerMock runner
+// TODO Specify which classes that must be prepared for test
+public class ProviderServiceImplTest_Tutorial {
+
+ private ProviderServiceImpl tested;
+ private ProviderDao providerDaoMock;
+
+
+ @Before
+ public void setUp() {
+ // TODO Create a mock object of the ProviderDao class
+ // TODO Create a new instance of ProviderServiceImpl
+ // TODO Set the providerDao mock to the providerDao field in the tested instance
+ }
+
+ @After
+ public void tearDown() {
+ // TODO Set all references to null
+ }
+
+ @Test
+ public void testGetAllServiceProviders() throws Exception {
+ // TODO Create a partial mock of the ProviderServiceImpl mocking only the getAllServiceProducers method
+ // TODO Create a new HashSet of ServiceProducer's and add a ServiceProducer to the set
+ // TODO Expect the private method call to getAllServiceProducers and return the created HashSet
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ }
+
+ @Test
+ public void testGetAllServiceProviders_noServiceProvidersFound() throws Exception {
+ // TODO Create a partial mock of the ProviderServiceImpl mocking only the getAllServiceProducers method
+ // TODO Expect the private method call to getAllServiceProducers and return null
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ }
+
+ @Test
+ public void testServiceProvider_found() throws Exception {
+ // TODO Create a partial mock of the ProviderServiceImpl mocking only the getAllServiceProducers method
+ // TODO Create a new HashSet of ServiceProducer's and add a ServiceProducer to the set
+ // TODO Expect the private method call to getAllServiceProducers and return the created HashSet
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ }
+
+ @Test
+ public void testServiceProvider_notFound() throws Exception {
+ // TODO Create a partial mock of the ProviderServiceImpl mocking only the getAllServiceProducers method
+ // TODO Expect the private method call to getAllServiceProducers and return null
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ }
+
+ @Test
+ public void getAllServiceProducers() throws Exception {
+ // TODO Create a new ServiceArtifact and a new HashSet place the created ServiceArtifact in this set
+ // TODO Expect the call to the providerDao.getAllServiceProducers(..) and return the HashSet
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test by invoking the private "getAllServiceProducers" method. Assert that the result matches the expectations.
+ // TODO Verify all mock objects used
+ }
+
+ @Test
+ public void getAllServiceProducers_empty() throws Exception {
+ // TODO Create a new HashSet of ServiceArtifacts
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test by invoking the private "getAllServiceProducers" method. Assert that the result matches the expectations.
+ // TODO Verify all mock objects used
+ }
+}
diff --git a/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest_Tutorial.java b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest_Tutorial.java
new file mode 100644
index 0000000..2dcc3db
--- /dev/null
+++ b/examples/tutorial/src/tutorial/java/demo/org/powermock/examples/tutorial/staticmocking/impl/ServiceRegistratorTest_Tutorial.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.examples.tutorial.staticmocking.impl;
+
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.BundleContext;
+import demo.org.powermock.examples.tutorial.staticmocking.osgi.ServiceRegistration;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * The purpose of this test is to get 100% coverage of the
+ * {@link ServiceRegistrator} class without any code changes to that class. To
+ * achieve this you need learn how to mock static methods as well as how to set
+ * and get internal state of an object.
+ * <p>
+ * While doing this tutorial please refer to the documentation on how to mock
+ * static methods and bypass encapsulation at the PowerMock web site.
+ */
+// TODO Specify the PowerMock runner
+// TODO Specify which classes that must be prepared for test
+public class ServiceRegistratorTest_Tutorial {
+
+ private BundleContext bundleContextMock;
+ private ServiceRegistration serviceRegistrationMock;
+ private ServiceRegistrator tested;
+
+ @Before
+ public void setUp() {
+ // TODO Create a mock object of the BundleContext and ServiceRegistration classes
+ // TODO Create a new instance of SampleServiceImpl and pass in the created mock objects to the constructor
+ // TODO Prepare the IdGenerator for static mocking
+ }
+
+ @After
+ public void tearDown() {
+ // TODO Set all references to null
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#registerService(String, Object)}
+ * method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testRegisterService() throws Exception {
+ // TODO Set the bundle context mock to the correct field in the tested instance
+ // TODO Expect the call to bundleContextMock.registerService(..) and return a mock
+ // TODO Expect the static method call to IdGenerator.generateNewId() and return a known id
+ // TODO Replay all mock objects used and the class containing the static method
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used and the class containing the static method
+ // TODO Assert that the serviceRegistrations map in the test instance has been updated correctly
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#unregisterService(long)} method.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService() throws Exception {
+ // TODO Create a new HashMap of ServiceRegistration's and add a new ServiceRegistration to the map.
+ // TODO Set the new HashMap to the serviceRegistrations field in the tested instance
+ // TODO Expect the call to serviceRegistrationMock.unregister()
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ // TODO Assert that the serviceRegistrations map in the test instance has been updated correctly
+ }
+
+ /**
+ * Test for the {@link ServiceRegistrator#unregisterService(long)} method
+ * when the ID doesn't exist.
+ *
+ * @throws Exception
+ * If an error occurs.
+ */
+ @Test
+ public void testUnregisterService_idDoesntExist() throws Exception {
+ // TODO Create a new HashMap of ServiceRegistration's and set it to the serviceRegistrations field in the tested instance
+ // TODO Expect the call to serviceRegistrationMock.unregister() and throw an IllegalStateException
+ // TODO Replay all mock objects used
+ // TODO Perform the actual test and assert that the result matches the expectations
+ // TODO Verify all mock objects used
+ // TODO Assert that the serviceRegistrations map in the test instance has not been updated
+ }
+}
diff --git a/generate_javadoc.sh b/generate_javadoc.sh
new file mode 100755
index 0000000..ca51957
--- /dev/null
+++ b/generate_javadoc.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+read -p "Version to generate javadoc for: " version
+project_names=(powermock-core powermock-api-easymock powermock-api-mockito powermock-api-mockito2 powermock-api-mockito-common\
+ powermock-reflect powermock-api-support powermock-module-junit4-common powermock-module-junit4 powermock-module-junit4-rule\
+ powermock-classloading-module powermock-classloading-xstream powermock-module-javaagent powermock-module-junit4-rule-agent\
+ powermock-module-junit3 powermock-module-junit4-legacy powermock-module-testng-common powermock-module-testng\
+ powermock-module-testng-agent powermock-modules-impl powermock-classloading-objenesis)
+
+echo "Generating Javadoc for version ${version}."
+
+for project_name in ${project_names[*]}
+do
+ echo "Generating for ${project_name}"
+ curl -Ss http://www.javadoc.io/doc/org.powermock/${project_name}/${version} >/dev/null 2>&1
+done
+echo "Completed"
+
diff --git a/modules/module-impl/agent/META-INF/MANIFEST.MF b/modules/module-impl/agent/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..192493a
--- /dev/null
+++ b/modules/module-impl/agent/META-INF/MANIFEST.MF
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Premain-Class: org.powermock.modules.agent.PowerMockAgent
+Agent-Class: org.powermock.modules.agent.PowerMockAgent
+Can-Retransform-Classes: true
+Can-Redefine-Classes: true
diff --git a/modules/module-impl/agent/jmockit-license.txt b/modules/module-impl/agent/jmockit-license.txt
new file mode 100644
index 0000000..e880719
--- /dev/null
+++ b/modules/module-impl/agent/jmockit-license.txt
@@ -0,0 +1,21 @@
+The JMockit Testing Toolkit
+Copyright (c) 2006-2011 Rogério Liesenfeld
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/modules/module-impl/agent/pom.xml b/modules/module-impl/agent/pom.xml
new file mode 100644
index 0000000..e4406a4
--- /dev/null
+++ b/modules/module-impl/agent/pom.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-javaagent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock Java agent support.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>compile</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <archive>
+ <addMavenDescriptor>false</addMavenDescriptor>
+ <forced />
+ <manifestFile>${project.basedir}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentInitializationException.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentInitializationException.java
new file mode 100644
index 0000000..c31ab37
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentInitializationException.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach;
+
+/**
+ * The exception thrown when an agent fails to initialize in the target Java virtual machine.
+ * <p/>
+ * <p> This exception is thrown by {@link
+ * VirtualMachine#loadAgent VirtualMachine.loadAgent},
+ * {@link VirtualMachine#loadAgentLibrary
+ * VirtualMachine.loadAgentLibrary}, {@link
+ * VirtualMachine#loadAgentPath VirtualMachine.loadAgentPath}
+ * methods if an agent, or agent library, cannot be initialized.
+ * When thrown by <tt>VirtualMachine.loadAgentLibrary</tt>, or
+ * <tt>VirtualMachine.loadAgentPath</tt> then the exception encapsulates
+ * the error returned by the agent's <code>Agent_OnAttach</code> function.
+ * This error code can be obtained by invoking the {@link #returnValue() returnValue} method.
+ */
+public final class AgentInitializationException extends Exception
+{
+ private static final long serialVersionUID = -1508756333332806353L;
+
+ private final int returnValue;
+
+ /**
+ * Constructs an <code>AgentInitializationException</code> with
+ * no detail message.
+ */
+ public AgentInitializationException()
+ {
+ returnValue = 0;
+ }
+
+ /**
+ * Constructs an <code>AgentInitializationException</code> with the specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public AgentInitializationException(String s)
+ {
+ super(s);
+ returnValue = 0;
+ }
+
+ /**
+ * Constructs an <code>AgentInitializationException</code> with
+ * the specified detail message and the return value from the
+ * execution of the agent's <code>Agent_OnAttach</code> function.
+ *
+ * @param s the detail message.
+ * @param returnValue the return value
+ */
+ public AgentInitializationException(String s, int returnValue)
+ {
+ super(s);
+ this.returnValue = returnValue;
+ }
+
+ /**
+ * If the exception was created with the return value from the agent
+ * <code>Agent_OnAttach</code> function then this returns that value,
+ * otherwise returns <code>0</code>. </p>
+ */
+ public int returnValue()
+ {
+ return returnValue;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentLoadException.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentLoadException.java
new file mode 100644
index 0000000..816255a
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AgentLoadException.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach;
+
+/**
+ * The exception thrown when an agent cannot be loaded into the target Java virtual machine.
+ * <p/>
+ * <p> This exception is thrown by {@link
+ * VirtualMachine#loadAgent VirtualMachine.loadAgent} or
+ * {@link VirtualMachine#loadAgentLibrary
+ * VirtualMachine.loadAgentLibrary}, {@link VirtualMachine#loadAgentPath loadAgentPath} methods
+ * if the agent, or agent library, cannot be loaded.
+ */
+public final class AgentLoadException extends Exception
+{
+ private static final long serialVersionUID = 688047862952114238L;
+
+ /**
+ * Constructs an <code>AgentLoadException</code> with
+ * no detail message.
+ */
+ public AgentLoadException()
+ {
+ }
+
+ /**
+ * Constructs an <code>AgentLoadException</code> with the specified detail message.
+ */
+ public AgentLoadException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AttachNotSupportedException.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AttachNotSupportedException.java
new file mode 100644
index 0000000..7b59e6e
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/AttachNotSupportedException.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach;
+
+/**
+ * Thrown by {@link VirtualMachine#attach VirtalMachine.attach} when attempting to attach to a Java
+ * virtual machine for which a compatible {@link com.sun.tools.attach.spi.AttachProvider
+ * AttachProvider} does not exist. It is also thrown by {@link
+ * com.sun.tools.attach.spi.AttachProvider#attachVirtualMachine
+ * AttachProvider.attachVirtualMachine} if the provider attempts to
+ * attach to a Java virtual machine with which it not compatible.
+ */
+public final class AttachNotSupportedException extends Exception
+{
+ private static final long serialVersionUID = 3391824968260177264L;
+
+ /**
+ * Constructs an <code>AttachNotSupportedException</code> with no detail message.
+ */
+ public AttachNotSupportedException()
+ {
+ }
+
+ /**
+ * Constructs an <code>AttachNotSupportedException</code> with
+ * the specified detail message.
+ *
+ * @param s the detail message.
+ */
+ public AttachNotSupportedException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachine.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachine.java
new file mode 100644
index 0000000..dc20ccf
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachine.java
@@ -0,0 +1,530 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach;
+
+import com.sun.tools.attach.spi.AttachProvider;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * A Java virtual machine.
+ * <p/>
+ * <p> A <code>VirtualMachine</code> represents a Java virtual machine to which this
+ * Java virtual machine has attached. The Java virtual machine to which it is
+ * attached is sometimes called the <i>target virtual machine</i>, or <i>target VM</i>.
+ * An application (typically a tool such as a managemet console or profiler) uses a
+ * VirtualMachine to load an agent into the target VM. For example, a profiler tool
+ * written in the Java Language might attach to a running application and load its
+ * profiler agent to profile the running application. </p>
+ * <p/>
+ * <p> A VirtualMachine is obtained by invoking the {@link #attach(String) attach} method
+ * with an identifier that identifies the target virtual machine. The identifier is
+ * implementation-dependent but is typically the process identifier (or pid) in
+ * environments where each Java virtual machine runs in its own operating system process.
+ * Alternatively, a <code>VirtualMachine</code> instance is obtained by invoking the
+ * {@link #attach(VirtualMachineDescriptor) attach} method with a {@link
+ * com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor} obtained
+ * from the list of virtual machine descriptors returned by the {@link #list list} method.
+ * Once a reference to a virtual machine is obtained, the {@link #loadAgent loadAgent},
+ * {@link #loadAgentLibrary loadAgentLibrary}, and {@link #loadAgentPath loadAgentPath}
+ * methods are used to load agents into target virtual machine. The {@link
+ * #loadAgent loadAgent} method is used to load agents that are written in the Java
+ * Language and deployed in a {@link java.util.jar.JarFile JAR file}. (See
+ * {@link java.lang.instrument} for a detailed description on how these agents
+ * are loaded and started). The {@link #loadAgentLibrary loadAgentLibrary} and
+ * {@link #loadAgentPath loadAgentPath} methods are used to load agents that
+ * are deployed in a dynamic library and make use of the <a
+ * href="../../../../../../../../technotes/guides/jvmti/index.html">JVM Tools
+ * Interface</a>. </p>
+ * <p/>
+ * <p> In addition to loading agents a VirtualMachine provides read access to the
+ * {@link java.lang.System#getProperties() system properties} in the target VM.
+ * This can be useful in some environments where properties such as
+ * <code>java.home</code>, <code>os.name</code>, or <code>os.arch</code> are
+ * used to construct the path to agent that will be loaded into the target VM.
+ * <p/>
+ * <p> The following example demonstrates how VirtualMachine may be used:</p>
+ * <p/>
+ * <pre>
+ * <p/>
+ * // attach to target VM
+ * VirtualMachine vm = VirtualMachine.attach("2177");
+ * <p/>
+ * // get system properties in target VM
+ * Properties props = vm.getSystemProperties();
+ * <p/>
+ * // construct path to management agent
+ * String home = props.getProperty("java.home");
+ * String agent = home + File.separator + "lib" + File.separator
+ * + "management-agent.jar";
+ * <p/>
+ * // load agent into target VM
+ * vm.loadAgent(agent, "com.sun.management.jmxremote.port=5000");
+ * <p/>
+ * // detach
+ * vm.detach();
+ * <p/>
+ * </pre>
+ * <p/>
+ * <p> In this example we attach to a Java virtual machine that is identified by
+ * the process identifier <code>2177</code>. The system properties from the target
+ * VM are then used to construct the path to a <i>management agent</i> which is then
+ * loaded into the target VM. Once loaded the client detaches from the target VM. </p>
+ * <p/>
+ * <p> A VirtualMachine is safe for use by multiple concurrent threads. </p>
+ *
+ * @since 1.6
+ */
+public abstract class VirtualMachine
+{
+ private final AttachProvider provider;
+ private final String id;
+ private volatile int hash; // 0 => not computed
+
+ /**
+ * Initializes a new instance of this class.
+ *
+ * @param provider The attach provider creating this class.
+ * @param id The abstract identifier that identifies the Java virtual machine.
+ */
+ protected VirtualMachine(AttachProvider provider, String id)
+ {
+ this.provider = provider;
+ this.id = id;
+ }
+
+ /**
+ * Return a list of Java virtual machines.
+ * <p/>
+ * This method returns a list of Java {@link com.sun.tools.attach.VirtualMachineDescriptor}
+ * elements. The list is an aggregation of the virtual machine descriptor lists obtained by
+ * invoking the {@link com.sun.tools.attach.spi.AttachProvider#listVirtualMachines
+ * listVirtualMachines} method of all installed {@link com.sun.tools.attach.spi.AttachProvider
+ * attach providers}. If there are no Java virtual machines known to any provider then an empty
+ * list is returned.
+ *
+ * @return The list of virtual machine descriptors.
+ */
+ public static List<VirtualMachineDescriptor> list()
+ {
+ List<VirtualMachineDescriptor> l = new ArrayList<VirtualMachineDescriptor>();
+ List<AttachProvider> providers = AttachProvider.providers();
+
+ for (AttachProvider provider : providers) {
+ l.addAll(provider.listVirtualMachines());
+ }
+
+ return l;
+ }
+
+ /**
+ * Attaches to a Java virtual machine.
+ * <p/>
+ * This method obtains the list of attach providers by invoking the
+ * {@link com.sun.tools.attach.spi.AttachProvider#providers() AttachProvider.providers()} method.
+ * It then iterates overs the list and invokes each provider's {@link
+ * com.sun.tools.attach.spi.AttachProvider#attachVirtualMachine(java.lang.String)
+ * attachVirtualMachine} method in turn. If a provider successfully
+ * attaches then the iteration terminates, and the VirtualMachine created
+ * by the provider that successfully attached is returned by this method.
+ * If the <code>attachVirtualMachine</code> method of all providers throws
+ * {@link com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException}
+ * then this method also throws <code>AttachNotSupportedException</code>.
+ * This means that <code>AttachNotSupportedException</code> is thrown when
+ * the identifier provided to this method is invalid, or the identifier
+ * corresponds to a Java virtual machine that does not exist, or none
+ * of the providers can attach to it. This exception is also thrown if
+ * {@link com.sun.tools.attach.spi.AttachProvider#providers()
+ * AttachProvider.providers()} returns an empty list. </p>
+ *
+ * @param id The abstract identifier that identifies the Java virtual machine.
+ * @return A VirtualMachine representing the target VM.
+ * @throws SecurityException If a security manager has been installed and it denies
+ * {@link com.sun.tools.attach.AttachPermission AttachPermission}
+ * <tt>("attachVirtualMachine")</tt>, or another permission
+ * required by the implementation.
+ * @throws IOException If an I/O error occurs
+ */
+ public static VirtualMachine attach(String id) throws AttachNotSupportedException, IOException
+ {
+ List<AttachProvider> providers = AttachProvider.providers();
+ AttachNotSupportedException lastExc = null;
+
+ for (AttachProvider provider : providers) {
+ try {
+ return provider.attachVirtualMachine(id);
+ }
+ catch (AttachNotSupportedException x) {
+ lastExc = x;
+ }
+ }
+
+ throw lastExc;
+ }
+
+ /**
+ * Attaches to a Java virtual machine.
+ * <p/>
+ * This method first invokes the {@link com.sun.tools.attach.VirtualMachineDescriptor#provider()
+ * provider()} method of the given virtual machine descriptor to obtain the attach provider.
+ * It then invokes the attach provider's {@link
+ * com.sun.tools.attach.spi.AttachProvider#attachVirtualMachine(VirtualMachineDescriptor)
+ * attachVirtualMachine} to attach to the target VM.
+ *
+ * @param vmd The virtual machine descriptor.
+ *
+ * @return A VirtualMachine representing the target VM.
+ *
+ * @throws SecurityException
+ * If a security manager has been installed and it denies
+ * {@link com.sun.tools.attach.AttachPermission AttachPermission}
+ * <tt>("attachVirtualMachine")</tt>, or another permission
+ * required by the implementation.
+ *
+ * @throws AttachNotSupportedException
+ * If the attach provider's <code>attachVirtualmachine</code>
+ * throws <code>AttachNotSupportedException</code>.
+ *
+ * @throws IOException If an I/O error occurs
+ *
+ * @throws NullPointerException If <code>vmd</code> is <code>null</code>.
+ */
+ public static VirtualMachine attach(VirtualMachineDescriptor vmd)
+ throws AttachNotSupportedException, IOException
+ {
+ return vmd.provider().attachVirtualMachine(vmd);
+ }
+
+ /**
+ * Detach from the virtual machine.
+ * <p/>
+ * After detaching from the virtual machine, any further attempt to invoke
+ * operations on that virtual machine will cause an {@link java.io.IOException
+ * IOException} to be thrown. If an operation (such as {@link #loadAgent
+ * loadAgent} for example) is in progress when this method is invoked then
+ * the behaviour is implementation dependent. In other words, it is
+ * implementation specific if the operation completes or throws <tt>IOException</tt>.
+ * <p/>
+ * If already detached from the virtual machine then invoking this method has no effect.
+ *
+ * @throws IOException If an I/O error occurs
+ */
+ public abstract void detach() throws IOException;
+
+ /**
+ * Returns the provider that created this virtual machine.
+ */
+ public final AttachProvider provider()
+ {
+ return provider;
+ }
+
+ /**
+ * Returns the identifier for this Java virtual machine.
+ */
+ public final String id()
+ {
+ return id;
+ }
+
+ /**
+ * Loads an agent library.
+ * <p/>
+ * A <a href="../../../../../../../../technotes/guides/jvmti/index.html">JVM
+ * TI</a> client is called an <i>agent</i>. It is developed in a native language.
+ * A JVM TI agent is deployed in a platform specific manner but it is typically the
+ * platform equivalent of a dynamic library. This method causes the given agent
+ * library to be loaded into the target VM (if not already loaded).
+ * It then causes the target VM to invoke the <code>Agent_OnAttach</code> function
+ * as specified in the
+ * <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
+ * Interface</a> specification. Note that the <code>Agent_OnAttach</code>
+ * function is invoked even if the agent library was loaded prior to invoking
+ * this method.
+ * <p/>
+ * The agent library provided is the name of the agent library. It is interpreted
+ * in the target virtual machine in an implementation-dependent manner. Typically an
+ * implementation will expand the library name into an operating system specific file
+ * name. For example, on UNIX systems, the name <tt>foo</tt> might be expanded to
+ * <tt>libfoo.so</tt>, and located using the search path specified by the
+ * <tt>LD_LIBRARY_PATH</tt> environment variable.
+ * <p/>
+ * If the <code>Agent_OnAttach</code> function in the agent library returns
+ * an error then an {@link com.sun.tools.attach.AgentInitializationException} is
+ * thrown. The return value from the <code>Agent_OnAttach</code> can then be
+ * obtained by invoking the {@link
+ * com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
+ * method on the exception.
+ *
+ * @param agentLibrary The name of the agent library.
+ * @param options The options to provide to the <code>Agent_OnAttach</code>
+ * function (can be <code>null</code>).
+ * @throws AgentLoadException If the agent library does not exist, or cannot be loaded for
+ * another reason.
+ * @throws AgentInitializationException If the <code>Agent_OnAttach</code> function returns an error
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agentLibrary</code> is <code>null</code>.
+ * @see com.sun.tools.attach.AgentInitializationException#returnValue()
+ */
+ public abstract void loadAgentLibrary(String agentLibrary, String options)
+ throws AgentLoadException, AgentInitializationException, IOException;
+
+ /**
+ * Loads an agent library.
+ * <p/>
+ * This convenience method works as if by invoking:
+ * <p/>
+ * <blockquote><tt>
+ * {@link #loadAgentLibrary(String, String) loadAgentLibrary}(agentLibrary, null);
+ * </tt></blockquote>
+ *
+ * @param agentLibrary The name of the agent library.
+ * @throws AgentLoadException If the agent library does not exist, or cannot be loaded for
+ * another reason.
+ * @throws AgentInitializationException If the <code>Agent_OnAttach</code> function returns an error
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agentLibrary</code> is <code>null</code>.
+ */
+ public void loadAgentLibrary(String agentLibrary)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ loadAgentLibrary(agentLibrary, null);
+ }
+
+ /**
+ * Load a native agent library by full pathname.
+ * <p/>
+ * A <a href="../../../../../../../../technotes/guides/jvmti/index.html">JVM TI</a> client is
+ * called an <i>agent</i>. It is developed in a native language.
+ * A JVM TI agent is deployed in a platform specific manner but it is typically the
+ * platform equivalent of a dynamic library. This method causes the given agent
+ * library to be loaded into the target VM (if not already loaded).
+ * It then causes the target VM to invoke the <code>Agent_OnAttach</code> function
+ * as specified in the
+ * <a href="../../../../../../../../technotes/guides/jvmti/index.html"> JVM Tools
+ * Interface</a> specification. Note that the <code>Agent_OnAttach</code>
+ * function is invoked even if the agent library was loaded prior to invoking
+ * this method.
+ * <p/>
+ * The agent library provided is the absolute path from which to load the
+ * agent library. Unlike {@link #loadAgentLibrary loadAgentLibrary}, the library name
+ * is not expanded in the target virtual machine.
+ * <p/>
+ * If the <code>Agent_OnAttach</code> function in the agent library returns
+ * an error then an {@link com.sun.tools.attach.AgentInitializationException} is
+ * thrown. The return value from the <code>Agent_OnAttach</code> can then be
+ * obtained by invoking the {@link
+ * com.sun.tools.attach.AgentInitializationException#returnValue() returnValue}
+ * method on the exception.
+ *
+ * @param agentPath The full path of the agent library.
+ * @param options The options to provide to the <code>Agent_OnAttach</code>
+ * function (can be <code>null</code>).
+ * @throws AgentLoadException If the agent library does not exist, or cannot be loaded for
+ * another reason.
+ * @throws AgentInitializationException If the <code>Agent_OnAttach</code> function returns an error
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agentPath</code> is <code>null</code>.
+ * @see com.sun.tools.attach.AgentInitializationException#returnValue()
+ */
+ public abstract void loadAgentPath(String agentPath, String options)
+ throws AgentLoadException, AgentInitializationException, IOException;
+
+ /**
+ * Load a native agent library by full pathname.
+ * <p/>
+ * This convenience method works as if by invoking:
+ * <p/>
+ * <blockquote><tt>
+ * {@link #loadAgentPath(String, String) loadAgentPath}(agentLibrary, null);
+ * </tt></blockquote>
+ *
+ * @param agentPath The full path to the agent library.
+ * @throws AgentLoadException If the agent library does not exist, or cannot be loaded for
+ * another reason.
+ * @throws AgentInitializationException If the <code>Agent_OnAttach</code> function returns an error
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agentPath</code> is <code>null</code>.
+ */
+ public void loadAgentPath(String agentPath)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ loadAgentPath(agentPath, null);
+ }
+
+
+ /**
+ * Loads an agent.
+ * <p/>
+ * <p> The agent provided to this method is a path name to a JAR file on the file
+ * system of the target virtual machine. This path is passed to the target virtual
+ * machine where it is interpreted. The target virtual machine attempts to start
+ * the agent as specified by the {@link java.lang.instrument} specification.
+ * That is, the specified JAR file is added to the system class path (of the target
+ * virtual machine), and the <code>agentmain</code> method of the agent class, specified
+ * by the <code>Agent-Class</code> attribute in the JAR manifest, is invoked. This
+ * method completes when the <code>agentmain</code> method completes.
+ *
+ * @param agent Path to the JAR file containing the agent.
+ * @param options The options to provide to the agent's <code>agentmain</code>
+ * method (can be <code>null</code>).
+ * @throws AgentLoadException If the agent does not exist, or cannot be started in the manner
+ * specified in the {@link java.lang.instrument} specification.
+ * @throws AgentInitializationException If the <code>agentmain</code> throws an exception
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agent</code> is <code>null</code>.
+ */
+ public abstract void loadAgent(String agent, String options)
+ throws AgentLoadException, AgentInitializationException, IOException;
+
+ /**
+ * Loads an agent.
+ * <p/>
+ * This convenience method works as if by invoking:
+ * <p/>
+ * <blockquote><tt>
+ * {@link #loadAgent(String, String) loadAgent}(agent, null);
+ * </tt></blockquote>
+ *
+ * @param agent Path to the JAR file containing the agent.
+ * @throws AgentLoadException If the agent does not exist, or cannot be started in the manner
+ * specified in the {@link java.lang.instrument} specification.
+ * @throws AgentInitializationException If the <code>agentmain</code> throws an exception
+ * @throws IOException If an I/O error occurs
+ * @throws NullPointerException If <code>agent</code> is <code>null</code>.
+ */
+ public void loadAgent(String agent)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ loadAgent(agent, null);
+ }
+
+ /**
+ * Returns the current system properties in the target virtual machine.
+ * <p/>
+ * This method returns the system properties in the target virtual
+ * machine. Properties whose key or value is not a <tt>String</tt> are
+ * omitted. The method is approximately equivalent to the invocation of the
+ * method {@link java.lang.System#getProperties System.getProperties}
+ * in the target virtual machine except that properties with a key or
+ * value that is not a <tt>String</tt> are not included.
+ * <p/>
+ * This method is typically used to decide which agent to load into
+ * the target virtual machine with {@link #loadAgent loadAgent}, or
+ * {@link #loadAgentLibrary loadAgentLibrary}. For example, the
+ * <code>java.home</code> or <code>user.dir</code> properties might be
+ * use to create the path to the agent library or JAR file.
+ *
+ * @return The system properties
+ * @throws IOException If an I/O error occurs
+ * @see java.lang.System#getProperties
+ * @see #loadAgentLibrary
+ * @see #loadAgent
+ */
+ public abstract Properties getSystemProperties() throws IOException;
+
+ /**
+ * Returns the current <i>agent properties</i> in the target virtual
+ * machine.
+ * <p/>
+ * The target virtual machine can maintain a list of properties on
+ * behalf of agents. The manner in which this is done, the names of the
+ * properties, and the types of values that are allowed, is implementation
+ * specific. Agent properties are typically used to store communication
+ * end-points and other agent configuration details. For example, a debugger
+ * agent might create an agent property for its transport address.
+ * <p/>
+ * This method returns the agent properties whose key and value is a
+ * <tt>String</tt>. Properties whose key or value is not a <tt>String</tt>
+ * are omitted. If there are no agent properties maintained in the target
+ * virtual machine then an empty property list is returned.
+ *
+ * @return The agent properties
+ * @throws IOException If an I/O error occurs
+ */
+ public abstract Properties getAgentProperties() throws IOException;
+
+ /**
+ * Returns a hash-code value for this VirtualMachine. The hash
+ * code is based upon the VirtualMachine's components, and satisfies
+ * the general contract of the Object.hashCode method.
+ *
+ * @return A hash-code value for this virtual machine
+ */
+ @Override
+ public int hashCode()
+ {
+ if (hash != 0) {
+ return hash;
+ }
+
+ hash = provider.hashCode() * 127 + id.hashCode();
+ return hash;
+ }
+
+ /**
+ * Tests this VirtualMachine for equality with another object.
+ * <p/>
+ * <p> If the given object is not a VirtualMachine then this
+ * method returns <tt>false</tt>. For two VirtualMachines to
+ * be considered equal requires that they both reference the same
+ * provider, and their {@link VirtualMachineDescriptor#id() identifiers} are equal. </p>
+ * <p/>
+ * <p> This method satisfies the general contract of the {@link
+ * java.lang.Object#equals(Object) Object.equals} method. </p>
+ *
+ * @param ob The object to which this object is to be compared
+ * @return <tt>true</tt> if, and only if, the given object is
+ * a VirtualMachine that is equal to this
+ * VirtualMachine.
+ */
+ @Override
+ public boolean equals(Object ob)
+ {
+ if (ob == this) {
+ return true;
+ }
+
+ if (!(ob instanceof VirtualMachine)) {
+ return false;
+ }
+
+ VirtualMachine other = (VirtualMachine) ob;
+
+ return other.provider() == provider() && other.id().equals(id());
+ }
+
+ /**
+ * Returns the string representation of the <code>VirtualMachine</code>.
+ */
+ @Override
+ public String toString()
+ {
+ return provider.toString() + ": " + id;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachineDescriptor.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachineDescriptor.java
new file mode 100644
index 0000000..32f31e3
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/VirtualMachineDescriptor.java
@@ -0,0 +1,211 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach;
+
+import com.sun.tools.attach.spi.AttachProvider;
+
+/**
+ * Describes a Java virtual machine.
+ * <p/>
+ * <p> A <code>VirtualMachineDescriptor</code> is a container class used to
+ * describe a Java virtual machine. It encapsulates an identifier that identifies
+ * a target virtual machine, and a reference to the {@link
+ * com.sun.tools.attach.spi.AttachProvider AttachProvider} that should be used
+ * when attempting to attach to the virtual machine. The identifier is
+ * implementation-dependent but is typically the process identifier (or pid)
+ * environments where each Java virtual machine runs in its own operating system
+ * process. </p>
+ * <p/>
+ * <p> A <code>VirtualMachineDescriptor</code> also has a {@link #displayName() displayName}.
+ * The display name is typically a human readable string that a tool might
+ * display to a user. For example, a tool that shows a list of Java
+ * virtual machines running on a system might use the display name rather
+ * than the identifier. A <code>VirtualMachineDescriptor</code> may be
+ * created without a <i>display name</i>. In that case the identifier is
+ * used as the <i>display name</i>.
+ * <p/>
+ * <p> <code>VirtualMachineDescriptor</code> instances are typically created by
+ * invoking the {@link VirtualMachine#list VirtualMachine.list()}
+ * method. This returns the complete list of descriptors to describe the
+ * Java virtual machines known to all installed {@link
+ * com.sun.tools.attach.spi.AttachProvider attach providers}.
+ *
+ * @since 1.6
+ */
+public final class VirtualMachineDescriptor
+{
+ private AttachProvider provider;
+ private String id;
+ private String displayName;
+
+ private volatile int hash; // 0 => not computed
+
+ /**
+ * Creates a virtual machine descriptor from the given components.
+ *
+ * @param provider The AttachProvider to attach to the Java virtual machine.
+ * @param id The virtual machine identifier.
+ * @param displayName The display name.
+ * @throws NullPointerException If any of the arguments are <code>null</code>
+ */
+ public VirtualMachineDescriptor(AttachProvider provider, String id, String displayName)
+ {
+ if (provider == null) {
+ throw new NullPointerException("provider cannot be null");
+ }
+
+ if (id == null) {
+ throw new NullPointerException("identifier cannot be null");
+ }
+
+ if (displayName == null) {
+ throw new NullPointerException("display name cannot be null");
+ }
+
+ this.provider = provider;
+ this.id = id;
+ this.displayName = displayName;
+ }
+
+ /**
+ * Creates a virtual machine descriptor from the given components.
+ * <p/>
+ * <p> This convenience constructor works as if by invoking the
+ * three-argument constructor as follows:
+ * <p/>
+ * <blockquote><tt>
+ * new {@link #VirtualMachineDescriptor(com.sun.tools.attach.spi.AttachProvider, String, String)
+ * VirtualMachineDescriptor}(provider, id, id);
+ * </tt></blockquote>
+ * <p/>
+ * <p> That is, it creates a virtual machine descriptor such that
+ * the <i>display name</i> is the same as the virtual machine
+ * identifier.
+ *
+ * @param provider The AttachProvider to attach to the Java virtual machine.
+ * @param id The virtual machine identifier.
+ * @throws NullPointerException If <tt>provider</tt> or <tt>id</tt> is <tt>null</tt>.
+ */
+ public VirtualMachineDescriptor(AttachProvider provider, String id)
+ {
+ this(provider, id, id);
+ }
+
+ /**
+ * Return the <code>AttachProvider</code> that this descriptor references.
+ *
+ * @return The <code>AttachProvider</code> that this descriptor references.
+ */
+ public AttachProvider provider()
+ {
+ return provider;
+ }
+
+ /**
+ * Return the identifier component of this descriptor.
+ *
+ * @return The identifier component of this descriptor.
+ */
+ public String id()
+ {
+ return id;
+ }
+
+ /**
+ * Return the <i>display name</i> component of this descriptor.
+ *
+ * @return The display name component of this descriptor.
+ */
+ public String displayName()
+ {
+ return displayName;
+ }
+
+ /**
+ * Returns a hash-code value for this VirtualMachineDescriptor. The hash
+ * code is based upon the descriptor's components, and satisfies
+ * the general contract of the Object.hashCode method.
+ *
+ * @return A hash-code value for this descriptor.
+ */
+ @Override
+ public int hashCode()
+ {
+ if (hash != 0) {
+ return hash;
+ }
+
+ hash = provider.hashCode() * 127 + id.hashCode();
+ return hash;
+ }
+
+ /**
+ * Tests this VirtualMachineDescriptor for equality with another object.
+ * <p/>
+ * <p> If the given object is not a VirtualMachineDescriptor then this
+ * method returns <tt>false</tt>. For two VirtualMachineDescriptors to
+ * be considered equal requires that they both reference the same
+ * provider, and their {@link #id() identifiers} are equal. </p>
+ * <p/>
+ * <p> This method satisfies the general contract of the {@link
+ * Object#equals(Object) Object.equals} method. </p>
+ *
+ * @param ob The object to which this object is to be compared
+ * @return <tt>true</tt> if, and only if, the given object is
+ * a VirtualMachineDescriptor that is equal to this
+ * VirtualMachineDescriptor.
+ */
+ @Override
+ public boolean equals(Object ob)
+ {
+ if (ob == this)
+ return true;
+ if (!(ob instanceof VirtualMachineDescriptor))
+ return false;
+ VirtualMachineDescriptor other = (VirtualMachineDescriptor) ob;
+ if (other.provider() != this.provider()) {
+ return false;
+ }
+ if (!other.id().equals(this.id())) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the string representation of the <code>VirtualMachineDescriptor</code>.
+ */
+ @Override
+ public String toString()
+ {
+ String s = provider.toString() + ": " + id;
+
+ if (displayName != id) {
+ s += " " + displayName;
+ }
+
+ return s;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/com/sun/tools/attach/spi/AttachProvider.java b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/spi/AttachProvider.java
new file mode 100644
index 0000000..98e8084
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/com/sun/tools/attach/spi/AttachProvider.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+package com.sun.tools.attach.spi;
+
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.VirtualMachineDescriptor;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.ServiceLoader;
+
+/**
+ * Attach provider class for attaching to a Java virtual machine.
+ * <p/>
+ * <p> An attach provider is a concrete subclass of this class that has a
+ * zero-argument constructor and implements the abstract methods specified
+ * below. </p>
+ * <p/>
+ * <p> An attach provider implementation is typically tied to a Java virtual
+ * machine implementation, version, or even mode of operation. That is, a specific
+ * provider implementation will typically only be capable of attaching to
+ * a specific Java virtual machine implementation or version. For example, Sun's
+ * JDK implementation ships with provider implementations that can only attach to
+ * Sun's <i>HotSpot</i> virtual machine. In general, if an environment
+ * consists of Java virtual machines of different versions and from different
+ * vendors then there will be an attach provider implementation for each
+ * <i>family</i> of implementations or versions. </p>
+ * <p/>
+ * <p> An attach provider is identified by its {@link #name <i>name</i>} and
+ * {@link #type <i>type</i>}. The <i>name</i> is typically, but not required to
+ * be, a name that corresponds to the VM vendor. The Sun JDK implementation,
+ * for example, ships with attach providers that use the name <i>"sun"</i>. The
+ * <i>type</i> typically corresponds to the attach mechanism. For example, an
+ * implementation that uses the Doors inter-process communication mechanism
+ * might use the type <i>"doors"</i>. The purpose of the name and type is to
+ * identify providers in environments where there are multiple providers
+ * installed. </p>
+ * <p/>
+ * <p> AttachProvider implementations are loaded and instantiated at the first
+ * invocation of the {@link #providers() providers} method. This method
+ * attempts to load all provider implementations that are installed on the
+ * platform. </p>
+ * <p/>
+ * <p> All of the methods in this class are safe for use by multiple
+ * concurrent threads. </p>
+ *
+ * @since 1.6
+ */
+public abstract class AttachProvider
+{
+ private static final Object lock = new Object();
+ private static List<AttachProvider> providers;
+
+ /**
+ * Initializes a new instance of this class.
+ */
+ protected AttachProvider() {}
+
+ /**
+ * Return this provider's name.
+ *
+ * @return The name of this provider
+ */
+ public abstract String name();
+
+ /**
+ * Return this provider's type.
+ *
+ * @return The type of this provider
+ */
+ public abstract String type();
+
+ /**
+ * Attaches to a Java virtual machine.
+ * <p/>
+ * <p> A Java virtual machine is identified by an abstract identifier. The
+ * nature of this identifier is platform dependent but in many cases it will be the
+ * string representation of the process identifier (or pid). </p>
+ * <p/>
+ * <p> This method parses the identifier and maps the identifier to a Java
+ * virtual machine (in an implementation dependent manner). If the identifier
+ * cannot be parsed by the provider then an {@link
+ * com.sun.tools.attach.AttachNotSupportedException AttachNotSupportedException}
+ * is thrown. Once parsed this method attempts to attach to the Java virtual machine.
+ * If the provider detects that the identifier corresponds to a Java virtual machine
+ * that does not exist, or it corresponds to a Java virtual machine that does not support
+ * the attach mechanism implemented by this provider, or it detects that the
+ * Java virtual machine is a version to which this provider cannot attach, then
+ * an <code>AttachNotSupportedException</code> is thrown. </p>
+ *
+ * @param id The abstract identifier that identifies the Java virtual machine.
+ * @return VirtualMachine representing the target virtual machine.
+ * @throws SecurityException If a security manager has been installed and it denies
+ * {@link com.sun.tools.attach.AttachPermission AttachPermission}
+ * <tt>("attachVirtualMachine")</tt>, or other permission
+ * required by the implementation.
+ * @throws AttachNotSupportedException If the identifier cannot be parsed, or it corresponds to
+ * to a Java virtual machine that does not exist, or it
+ * corresponds to a Java virtual machine which this
+ * provider cannot attach.
+ * @throws IOException If some other I/O error occurs
+ * @throws NullPointerException If <code>id</code> is <code>null</code>
+ */
+ public abstract VirtualMachine attachVirtualMachine(String id)
+ throws AttachNotSupportedException, IOException;
+
+ /**
+ * Attaches to a Java virtual machine.
+ * <p/>
+ * A Java virtual machine can be described using a {@link
+ * com.sun.tools.attach.VirtualMachineDescriptor VirtualMachineDescriptor}.
+ * This method invokes the descriptor's {@link
+ * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method
+ * to check that it is equal to this provider. It then attempts to attach to the
+ * Java virtual machine.
+ *
+ * @param vmd The virtual machine descriptor
+ * @return VirtualMachine representing the target virtual machine.
+ * @throws SecurityException If a security manager has been installed and it denies
+ * {@link com.sun.tools.attach.AttachPermission AttachPermission}
+ * <tt>("attachVirtualMachine")</tt>, or other permission
+ * required by the implementation.
+ * @throws AttachNotSupportedException If the descriptor's {@link
+ * com.sun.tools.attach.VirtualMachineDescriptor#provider() provider()} method
+ * returns a provider that is not this provider, or it does not correspond
+ * to a Java virtual machine to which this provider can attach.
+ * @throws IOException If some other I/O error occurs
+ * @throws NullPointerException If <code>vmd</code> is <code>null</code>
+ */
+ public VirtualMachine attachVirtualMachine(VirtualMachineDescriptor vmd)
+ throws AttachNotSupportedException, IOException
+ {
+ if (vmd.provider() != this) {
+ throw new AttachNotSupportedException("provider mismatch");
+ }
+
+ return attachVirtualMachine(vmd.id());
+ }
+
+ /**
+ * Lists the Java virtual machines known to this provider.
+ * <p/>
+ * This method returns a list of {@link com.sun.tools.attach.VirtualMachineDescriptor} elements.
+ * Each <code>VirtualMachineDescriptor</code> describes a Java virtual machine
+ * to which this provider can <i>potentially</i> attach. There isn't any
+ * guarantee that invoking {@link #attachVirtualMachine(VirtualMachineDescriptor)
+ * attachVirtualMachine} on each descriptor in the list will succeed.
+ *
+ * @return The list of virtual machine descriptors which describe the
+ * Java virtual machines known to this provider (may be empty).
+ */
+ public abstract List<VirtualMachineDescriptor> listVirtualMachines();
+
+ /**
+ * Returns a list of the installed attach providers.
+ * <p/>
+ * <p> An AttachProvider is installed on the platform if:
+ * <p/>
+ * <ul>
+ * <li><p>It is installed in a JAR file that is visible to the defining
+ * class loader of the AttachProvider type (usually, but not required
+ * to be, the {@link java.lang.ClassLoader#getSystemClassLoader system
+ * class loader}).</p></li>
+ * <p/>
+ * <li><p>The JAR file contains a provider configuration named
+ * <tt>com.sun.tools.attach.spi.AttachProvider</tt> in the resource directory
+ * <tt>META-INF/services</tt>. </p></li>
+ * <p/>
+ * <li><p>The provider configuration file lists the full-qualified class
+ * name of the AttachProvider implementation. </p></li>
+ * </ul>
+ * <p/>
+ * <p> The format of the provider configuration file is one fully-qualified
+ * class name per line. Space and tab characters surrounding each class name,
+ * as well as blank lines are ignored. The comment character is
+ * <tt>'#'</tt> (<tt>0x23</tt>), and on each line all characters following
+ * the first comment character are ignored. The file must be encoded in
+ * UTF-8. </p>
+ * <p/>
+ * <p> AttachProvider implementations are loaded and instantiated
+ * (using the zero-arg constructor) at the first invocation of this method.
+ * The list returned by the first invocation of this method is the list
+ * of providers. Subsequent invocations of this method return a list of the same
+ * providers. The list is unmodifable.</p>
+ *
+ * @return A list of the installed attach providers.
+ */
+ @SuppressWarnings({"Since15"})
+ public static List<AttachProvider> providers()
+ {
+ synchronized (lock) {
+ if (providers == null) {
+ providers = new ArrayList<AttachProvider>();
+
+ ServiceLoader<AttachProvider> providerLoader =
+ ServiceLoader.load(AttachProvider.class, AttachProvider.class.getClassLoader());
+
+ for (AttachProvider aProviderLoader : providerLoader) {
+ try {
+ providers.add(aProviderLoader);
+ }
+ catch (ThreadDeath td) {
+ throw td;
+ }
+ catch (Throwable t) {
+ // Ignore errors and exceptions.
+ System.err.println(t);
+ }
+ }
+ }
+
+ return Collections.unmodifiableList(providers);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AbstractClassTransformer.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AbstractClassTransformer.java
new file mode 100644
index 0000000..8a699c2
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AbstractClassTransformer.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.modules.agent;
+
+import org.powermock.core.WildcardMatcher;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+public abstract class AbstractClassTransformer {
+
+ private static final List<String> ALWAYS_IGNORED = new LinkedList<String>();
+ private final List<String> USER_IGNORED = Collections.synchronizedList(new LinkedList<String>());
+
+ static {
+ ALWAYS_IGNORED.add("org.powermock.*");
+ ALWAYS_IGNORED.add("org.junit.*");
+ ALWAYS_IGNORED.add("org.testng.*");
+ ALWAYS_IGNORED.add("org.assertj.*");
+ ALWAYS_IGNORED.add("org.mockito.*");
+ ALWAYS_IGNORED.add("javassist.*");
+ ALWAYS_IGNORED.add("org.objenesis.*");
+ ALWAYS_IGNORED.add("junit.*");
+ ALWAYS_IGNORED.add("org.hamcrest.*");
+ ALWAYS_IGNORED.add("sun.*");
+ ALWAYS_IGNORED.add("$Proxy*");
+ ALWAYS_IGNORED.add("*CGLIB$$*");
+ ALWAYS_IGNORED.add("*$$PowerMock*");
+ }
+
+ public synchronized void setPackagesToIgnore(List<String> packagesToIgnore) {
+ USER_IGNORED.clear();
+ USER_IGNORED.addAll(packagesToIgnore);
+ }
+
+ public void resetPackagesToIgnore() {
+ USER_IGNORED.clear();
+ }
+
+ protected boolean shouldIgnore(String className) {
+ return WildcardMatcher.matchesAny(merge(USER_IGNORED), replaceSlashWithDots(className));
+ }
+
+ private List<String> merge(List<String> userIgnored) {
+ List<String> list = new LinkedList<String>(AbstractClassTransformer.ALWAYS_IGNORED);
+ list.addAll(userIgnored);
+ return Collections.unmodifiableList(list);
+ }
+
+ String replaceSlashWithDots(String className) {
+ return className.replaceAll("/", ".");
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentInitialization.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentInitialization.java
new file mode 100644
index 0000000..40feb69
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentInitialization.java
@@ -0,0 +1,101 @@
+/*
+ * The JMockit Testing Toolkit
+ * Copyright (c) 2006-2011 Rogério Liesenfeld
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.powermock.modules.agent;
+
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.CodeSource;
+import java.util.regex.Pattern;
+
+final class AgentInitialization
+{
+ private static final Pattern JAR_REGEX = Pattern.compile(".*powermock-module-javaagent[-]?[.\\d+]*[-]?[A-Z]*.jar");
+
+ void initializeAccordingToJDKVersion() {
+ String jarFilePath = discoverPathToJarFile();
+
+ if (PowerMockAgent.jdk6OrLater) {
+ new AgentLoader(jarFilePath).loadAgent();
+ }
+ else if ("1.5".equals(PowerMockAgent.javaSpecVersion)) {
+ throw new IllegalStateException(
+ "PowerMock has not been initialized. Check that your Java 5 VM has been started with the -javaagent:" +
+ jarFilePath + " command line option.");
+ }
+ else {
+ throw new IllegalStateException("PowerMock requires a Java 5 VM or later.");
+ }
+ }
+
+ private String discoverPathToJarFile()
+ {
+ String jarFilePath = findPathToJarFileFromClasspath();
+
+ if (jarFilePath == null) {
+ // This can fail for a remote URL, so it is used as a fallback only:
+ jarFilePath = getPathToJarFileContainingThisClass();
+ }
+
+ if (jarFilePath != null) {
+ return jarFilePath;
+ }
+
+ throw new IllegalStateException(
+ "No jar file with name ending in \"powermock-module-javaagent.jar\" or \"powermock-module-javaagent-nnn.jar\" (where \"nnn\" is a version number) " +
+ "found in the classpath");
+ }
+
+ private String findPathToJarFileFromClasspath()
+ {
+ String[] classPath = System.getProperty("java.class.path").split(File.pathSeparator);
+
+ for (String cpEntry : classPath) {
+ if (JAR_REGEX.matcher(cpEntry).matches()) {
+ return cpEntry;
+ }
+ }
+
+ return null;
+ }
+
+ private String getPathToJarFileContainingThisClass() {
+ CodeSource codeSource = AgentInitialization.class.getProtectionDomain().getCodeSource();
+
+ if (codeSource == null) {
+ return null;
+ }
+
+ URI jarFileURI; // URI is needed to deal with spaces and non-ASCII characters
+
+ try {
+ jarFileURI = codeSource.getLocation().toURI();
+ }
+ catch (URISyntaxException e) {
+ throw new RuntimeException(e);
+ }
+
+ return new File(jarFileURI).getPath();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentLoader.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentLoader.java
new file mode 100644
index 0000000..292329c
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/AgentLoader.java
@@ -0,0 +1,152 @@
+/*
+ * The JMockit Testing Toolkit
+ * Copyright (c) 2006-2011 Rogério Liesenfeld
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.powermock.modules.agent;
+
+import com.sun.tools.attach.*;
+import com.sun.tools.attach.spi.AttachProvider;
+import org.powermock.reflect.Whitebox;
+import sun.tools.attach.BsdVirtualMachine;
+import sun.tools.attach.LinuxVirtualMachine;
+import sun.tools.attach.SolarisVirtualMachine;
+import sun.tools.attach.WindowsVirtualMachine;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.management.ManagementFactory;
+import java.util.List;
+
+final class AgentLoader {
+ private static final AttachProvider ATTACH_PROVIDER = new AttachProvider() {
+ @Override
+ public String name() {
+ return null;
+ }
+
+ @Override
+ public String type() {
+ return null;
+ }
+
+ @Override
+ public VirtualMachine attachVirtualMachine(String id) {
+ return null;
+ }
+
+ @Override
+ public List<VirtualMachineDescriptor> listVirtualMachines() {
+ return null;
+ }
+ };
+
+ private final String jarFilePath;
+ private final String pid;
+
+ AgentLoader(String jarFilePath) {
+ this.jarFilePath = jarFilePath;
+ pid = discoverProcessIdForRunningVM();
+ }
+
+ private static String discoverProcessIdForRunningVM() {
+ String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
+ int p = nameOfRunningVM.indexOf('@');
+
+ return nameOfRunningVM.substring(0, p);
+ }
+
+ boolean loadAgent() {
+ VirtualMachine vm;
+
+ if (AttachProvider.providers().isEmpty()) {
+ vm = getVirtualMachineImplementationFromEmbeddedOnes();
+ } else {
+ vm = attachToThisVM();
+ }
+
+ if (vm != null) {
+ loadAgentAndDetachFromThisVM(vm);
+ return true;
+ }
+
+ return false;
+ }
+
+ @SuppressWarnings("UseOfSunClasses")
+ private VirtualMachine getVirtualMachineImplementationFromEmbeddedOnes() {
+ try {
+ Class<? extends VirtualMachine> vmClass;
+
+ if (File.separatorChar == '\\') {
+ vmClass = WindowsVirtualMachine.class;
+ } else {
+ String osName = System.getProperty("os.name");
+
+ if (osName.startsWith("Linux") || osName.startsWith("LINUX")) {
+ vmClass = LinuxVirtualMachine.class;
+ } else if (osName.startsWith("Mac OS X")) {
+ vmClass = BsdVirtualMachine.class;
+ } else if (osName.startsWith("Solaris")) {
+ vmClass = SolarisVirtualMachine.class;
+ } else {
+ return null;
+ }
+ }
+
+ // This is only done with Reflection to avoid the JVM pre-loading all the XyzVirtualMachine classes.
+ Class<?>[] parameterTypes = {AttachProvider.class, String.class};
+
+ VirtualMachine newVM = null;
+ try {
+ newVM = Whitebox.invokeConstructor(vmClass, parameterTypes, new Object[]{ATTACH_PROVIDER, pid});
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ return newVM;
+ } catch (UnsatisfiedLinkError e) {
+ throw new IllegalStateException("Native library for Attach API not available in this JRE", e);
+ }
+ }
+
+ private VirtualMachine attachToThisVM() {
+ try {
+ return VirtualMachine.attach(pid);
+ } catch (AttachNotSupportedException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private void loadAgentAndDetachFromThisVM(VirtualMachine vm) {
+ try {
+ vm.loadAgent(jarFilePath, null);
+ vm.detach();
+ } catch (AgentLoadException e) {
+ throw new RuntimeException(e);
+ } catch (AgentInitializationException e) {
+ throw new RuntimeException(e);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/DefinalizingClassTransformer.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/DefinalizingClassTransformer.java
new file mode 100644
index 0000000..0fd688c
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/DefinalizingClassTransformer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.modules.agent;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+
+import org.powermock.objectweb.asm.ClassReader;
+import org.powermock.objectweb.asm.ClassWriter;
+
+public class DefinalizingClassTransformer extends AbstractClassTransformer implements ClassFileTransformer {
+
+
+
+ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+ if (loader == null || shouldIgnore(className)) {
+ return null;
+ }
+ final ClassReader reader = new ClassReader(classfileBuffer);
+ final ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ reader.accept(new PowerMockClassVisitor(writer),
+ ClassReader.SKIP_FRAMES);
+ return writer.toByteArray();
+ }
+
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockAgent.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockAgent.java
new file mode 100644
index 0000000..d6b0df3
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockAgent.java
@@ -0,0 +1,108 @@
+/*
+ * The JMockit Testing Toolkit
+ * Copyright (c) 2006-2011 Rogério Liesenfeld
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.powermock.modules.agent;
+
+import java.io.IOException;
+import java.lang.instrument.Instrumentation;
+
+/**
+ * This is the "agent class" that initializes the PowerMock "Java agent". It is not intended for use in client code.
+ * It must be public, however, so the JVM can call the {@code premain} method, which as the name implies is called
+ * <em>before</em> the {@code main} method.
+ *
+ * @see #premain(String, Instrumentation)
+ */
+public final class PowerMockAgent
+{
+
+ static final String javaSpecVersion = System.getProperty("java.specification.version");
+ static final boolean jdk6OrLater = "1.6".equals(javaSpecVersion) || "1.7".equals(javaSpecVersion) || "1.8".equals(javaSpecVersion);
+
+ private static final PowerMockClassTransformer classTransformer = new PowerMockClassTransformer();
+
+ private static Instrumentation instrumentation;
+
+ private PowerMockAgent() {}
+
+ public static boolean isJava6OrLater() { return jdk6OrLater; }
+
+ /**
+ * This method must only be called by the JVM, to provide the instrumentation object.
+ * In order for this to occur, the JVM must be started with "-javaagent:powermock-module-javaagent-nnn.jar" as a command line parameter
+ * (assuming the jar file is in the current directory).
+ *
+ */
+ public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+ initialize(agentArgs, inst);
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ public static void agentmain(String agentArgs, Instrumentation inst) throws Exception {
+ initialize(agentArgs, inst);
+ }
+
+ private static void initialize(String agentArgs, Instrumentation inst) throws IOException {
+ instrumentation = inst;
+ inst.addTransformer(new DefinalizingClassTransformer(), false);
+ inst.addTransformer(classTransformer, true);
+ }
+
+ public static PowerMockClassTransformer getClasstransformer() {
+ return classTransformer;
+ }
+
+ public static Instrumentation instrumentation() {
+ verifyInitialization();
+ return instrumentation;
+ }
+
+ public static void verifyInitialization()
+ {
+ if (instrumentation == null) {
+ new AgentInitialization().initializeAccordingToJDKVersion();
+ }
+ }
+
+ public static boolean initializeIfNeeded()
+ {
+ if (instrumentation == null) {
+ try {
+ new AgentInitialization().initializeAccordingToJDKVersion();
+ return true;
+ }
+ catch (RuntimeException e) {
+ e.printStackTrace(); // makes sure the exception gets printed at least once
+ throw e;
+ }
+ }
+
+ return false;
+ }
+
+ public static void initializeIfPossible() {
+ if (jdk6OrLater) {
+ initializeIfNeeded();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassRedefiner.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassRedefiner.java
new file mode 100644
index 0000000..bc04235
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassRedefiner.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.modules.agent;
+
+import org.powermock.core.agent.JavaAgentClassRegister;
+
+import java.util.Arrays;
+
+public class PowerMockClassRedefiner {
+
+ public static void redefine(String[] classes, String[] packagesToIgnore, JavaAgentClassRegister agentClassRegister) {
+ PowerMockClassTransformer transformer = PowerMockAgent.getClasstransformer();
+ transformer.setClassesToTransform(Arrays.asList(classes));
+ transformer.setPackagesToIgnore(Arrays.asList(packagesToIgnore));
+ transformer.setJavaAgentClassRegister(agentClassRegister);
+
+ try {
+ for (int i = classes.length - 1; i >= 0; i--) {
+ String className = classes[i];
+ Class<?> clazz;
+ try {
+ clazz = Class.forName(className);
+
+ PowerMockAgent.instrumentation().retransformClasses(clazz);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ } finally {
+ transformer.resetPackagesToIgnore();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassTransformer.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassTransformer.java
new file mode 100644
index 0000000..3ff6bcf
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassTransformer.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.agent;
+
+import javassist.ClassPool;
+import javassist.CtClass;
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.core.transformers.TransformStrategy;
+import org.powermock.core.transformers.impl.ClassMockTransformer;
+import org.powermock.core.transformers.impl.InterfaceMockTransformer;
+
+import java.io.ByteArrayInputStream;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.security.ProtectionDomain;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+class PowerMockClassTransformer extends AbstractClassTransformer implements ClassFileTransformer {
+
+ private volatile Set<String> classesToTransform;
+ private volatile JavaAgentClassRegister javaAgentClassRegister;
+
+ public void setClassesToTransform(Collection<String> classesToTransform) {
+ this.classesToTransform = new HashSet<String>(classesToTransform);
+ }
+
+ public void setJavaAgentClassRegister(JavaAgentClassRegister javaAgentClassRegister) {
+ this.javaAgentClassRegister = javaAgentClassRegister;
+ }
+
+ private static final ClassMockTransformer CLASS_MOCK_TRANSFORMER = new ClassMockTransformer(TransformStrategy.INST_REDEFINE);
+ private static final InterfaceMockTransformer INTERFACE_MOCK_TRANSFORMER = new InterfaceMockTransformer(TransformStrategy.INST_REDEFINE);
+
+ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+ if (loader == null || shouldIgnore(className)) {
+ return null;
+ }
+ try {
+ String normalizedClassName = className.replace("/", ".");
+ if (classesToTransform != null && classesToTransform.contains(normalizedClassName)) {
+ ByteArrayInputStream is = new ByteArrayInputStream(classfileBuffer);
+ CtClass ctClass = null;
+ try {
+ ctClass = ClassPool.getDefault().makeClass(is);
+ } finally {
+ is.close();
+ }
+
+ if (ctClass.isInterface()){
+ ctClass = INTERFACE_MOCK_TRANSFORMER.transform(ctClass);
+ }else{
+ ctClass = CLASS_MOCK_TRANSFORMER.transform(ctClass);
+ }
+
+ /*
+ * ClassPool may cause huge memory consumption if the number of CtClass
+ * objects becomes amazingly large (this rarely happens since Javassist
+ * tries to reduce memory consumption in various ways). To avoid this
+ * problem, you can explicitly remove an unnecessary CtClass object from
+ * the ClassPool. If you call detach() on a CtClass object, then that
+ * CtClass object is removed from the ClassPool.
+ */
+ ctClass.detach();
+
+ javaAgentClassRegister.registerClass(loader, normalizedClassName);
+
+ return ctClass.toBytecode();
+ }
+
+ return null;
+ } catch(Exception e) {
+ throw new RuntimeException("Failed to redefine class "+className, e);
+ }
+
+
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassVisitor.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassVisitor.java
new file mode 100644
index 0000000..6a78601
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/PowerMockClassVisitor.java
@@ -0,0 +1,35 @@
+package org.powermock.modules.agent;
+
+import org.powermock.objectweb.asm.ClassVisitor;
+import org.powermock.objectweb.asm.MethodVisitor;
+import org.powermock.objectweb.asm.Opcodes;
+
+class PowerMockClassVisitor extends ClassVisitor {
+
+ public PowerMockClassVisitor(ClassVisitor classVisitor) {
+ super(Opcodes.ASM5, classVisitor);
+ }
+
+ @Override
+ public void visit(final int version, final int access, final String name, final String signature, final String superName,
+ final String[] interfaces) {
+ final int accessModifiersWithFinalRemoved = removeFinal(access);
+ super.visit(version, accessModifiersWithFinalRemoved, name, signature, superName, interfaces);
+ }
+
+ @Override
+ public MethodVisitor visitMethod(int access, final String name, final String desc, final String signature,
+ final String[] exceptions) {
+ return super.visitMethod(removeFinal(access), name, desc, signature, exceptions);
+ }
+
+ @Override
+ public void visitInnerClass(String name, String outerName, String innerName, int access) {
+ super.visitInnerClass(name, outerName, innerName, removeFinal(access));
+ }
+
+ private int removeFinal(int access) {
+ return access & ~Opcodes.ACC_FINAL;
+ }
+
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/JavaAgentClassRegisterImpl.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/JavaAgentClassRegisterImpl.java
new file mode 100644
index 0000000..09b22c1
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/JavaAgentClassRegisterImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.agent.support;
+
+import org.powermock.core.agent.JavaAgentClassRegister;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Basic not thread-safety implementation of the {@link JavaAgentClassRegister}
+ */
+public class JavaAgentClassRegisterImpl implements JavaAgentClassRegister {
+
+ private final Map<ClassLoader, Set<String>> modifiedClasses;
+
+ public JavaAgentClassRegisterImpl() {
+ modifiedClasses = new HashMap<ClassLoader, Set<String>>();
+ }
+
+ @Override
+ public boolean isModifiedByAgent(ClassLoader classLoader, String className) {
+ return modifiedClasses.containsKey(classLoader) && modifiedClasses.get(classLoader).contains(className);
+ }
+
+ @Override
+ public void registerClass(ClassLoader loader, String className) {
+
+ Set<String> names = modifiedClasses.get(loader);
+ if (names == null){
+ names = new HashSet<String>();
+ modifiedClasses.put(loader, names);
+ }
+
+ names.add(className);
+
+ }
+
+ @Override
+ public void clear() {
+ modifiedClasses.clear();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/PowerMockAgentTestInitializer.java b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/PowerMockAgentTestInitializer.java
new file mode 100644
index 0000000..1260955
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/modules/agent/support/PowerMockAgentTestInitializer.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.agent.support;
+
+import org.powermock.core.MockRepository;
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.modules.agent.PowerMockClassRedefiner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.proxyframework.RegisterProxyFramework;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+import org.powermock.tests.utils.impl.PowerMockIgnorePackagesExtractorImpl;
+import org.powermock.tests.utils.impl.PrepareForTestExtractorImpl;
+import org.powermock.tests.utils.impl.StaticConstructorSuppressExtractorImpl;
+
+public class PowerMockAgentTestInitializer {
+
+ public static void initialize(Class<?> testClass, JavaAgentClassRegister agentClassRegister) {
+ /*
+ * For extra safety clear the MockitoRepository.
+ */
+ MockRepository.clear();
+
+ redefineClasses(testClass, agentClassRegister);
+
+ final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+
+ registerProxyFramework(contextClassLoader);
+
+ new MockPolicyInitializerImpl(testClass).initialize(contextClassLoader);
+ }
+
+ private static void redefineClasses(Class<?> testClass, JavaAgentClassRegister agentClassRegister) {
+ final String[] packagesToIgnore = new PowerMockIgnorePackagesExtractorImpl().getPackagesToIgnore(testClass);
+
+ redefineClassesToPrepare(testClass, packagesToIgnore, agentClassRegister);
+ redefineClassesToSuppress(testClass, packagesToIgnore, agentClassRegister);
+ }
+
+ private static void redefineClassesToSuppress(Class<?> testClass, String[] packagesToIgnore, JavaAgentClassRegister agentClassRegister) {
+ final String[] classesToSuppress = new StaticConstructorSuppressExtractorImpl().getTestClasses(testClass);
+ redefine(classesToSuppress, packagesToIgnore, agentClassRegister);
+ }
+
+ private static void redefineClassesToPrepare(Class<?> testClass, String[] packagesToIgnore,
+ JavaAgentClassRegister agentClassRegister) {
+ final String[] classesToPrepare = new PrepareForTestExtractorImpl(true).getTestClasses(testClass);
+ redefine(classesToPrepare, packagesToIgnore, agentClassRegister);
+ }
+
+ private static void redefine(String[] classes, String[] packagesToIgnore, JavaAgentClassRegister agentClassRegister) {
+ PowerMockClassRedefiner.redefine(classes, packagesToIgnore,agentClassRegister);
+ }
+
+ private static void registerProxyFramework(ClassLoader classLoader) {
+ final Class<?> proxyFrameworkClass;
+ try {
+ proxyFrameworkClass = Class.forName("org.powermock.api.extension.proxyframework.ProxyFrameworkImpl", false, classLoader);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(
+ "Extension API error: org.powermock.api.extension.proxyframework.ProxyFrameworkImpl could not be located in classpath.");
+ }
+
+ final Class<?> proxyFrameworkRegistrar;
+ try {
+ proxyFrameworkRegistrar = Class.forName(RegisterProxyFramework.class.getName(), false, classLoader);
+ } catch (ClassNotFoundException e) {
+ // Should never happen
+ throw new RuntimeException(e);
+ }
+ try {
+ Whitebox.invokeMethod(proxyFrameworkRegistrar, "registerProxyFramework", Whitebox.newInstance(proxyFrameworkClass));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationVisitor.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationVisitor.java
new file mode 100644
index 0000000..e7413ec
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationVisitor.java
@@ -0,0 +1,169 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A visitor to visit a Java annotation. The methods of this class must be
+ * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |
+ * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public abstract class AnnotationVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ protected final int api;
+
+ /**
+ * The annotation visitor to which this visitor must delegate method calls.
+ * May be null.
+ */
+ protected AnnotationVisitor av;
+
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ public AnnotationVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link AnnotationVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param av
+ * the annotation visitor to which this visitor must delegate
+ * method calls. May be null.
+ */
+ public AnnotationVisitor(final int api, final AnnotationVisitor av) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.av = av;
+ }
+
+ /**
+ * Visits a primitive value of the annotation.
+ *
+ * @param name
+ * the value name.
+ * @param value
+ * the actual value, whose type must be {@link Byte},
+ * {@link Boolean}, {@link Character}, {@link Short},
+ * {@link Integer} , {@link Long}, {@link Float}, {@link Double},
+ * {@link String} or {@link Type} or OBJECT or ARRAY sort. This
+ * value can also be an array of byte, boolean, short, char, int,
+ * long, float or double values (this is equivalent to using
+ * {@link #visitArray visitArray} and visiting each array element
+ * in turn, but is more convenient).
+ */
+ public void visit(String name, Object value) {
+ if (av != null) {
+ av.visit(name, value);
+ }
+ }
+
+ /**
+ * Visits an enumeration value of the annotation.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the enumeration class.
+ * @param value
+ * the actual enumeration value.
+ */
+ public void visitEnum(String name, String desc, String value) {
+ if (av != null) {
+ av.visitEnum(name, desc, value);
+ }
+ }
+
+ /**
+ * Visits a nested annotation value of the annotation.
+ *
+ * @param name
+ * the value name.
+ * @param desc
+ * the class descriptor of the nested annotation class.
+ * @return a visitor to visit the actual nested annotation value, or
+ * <tt>null</tt> if this visitor is not interested in visiting this
+ * nested annotation. <i>The nested annotation value must be fully
+ * visited before calling other methods on this annotation
+ * visitor</i>.
+ */
+ public AnnotationVisitor visitAnnotation(String name, String desc) {
+ if (av != null) {
+ return av.visitAnnotation(name, desc);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an array value of the annotation. Note that arrays of primitive
+ * types (such as byte, boolean, short, char, int, long, float or double)
+ * can be passed as value to {@link #visit visit}. This is what
+ * {@link ClassReader} does.
+ *
+ * @param name
+ * the value name.
+ * @return a visitor to visit the actual array value elements, or
+ * <tt>null</tt> if this visitor is not interested in visiting these
+ * values. The 'name' parameters passed to the methods of this
+ * visitor are ignored. <i>All the array values must be visited
+ * before calling other methods on this annotation visitor</i>.
+ */
+ public AnnotationVisitor visitArray(String name) {
+ if (av != null) {
+ return av.visitArray(name);
+ }
+ return null;
+ }
+
+ /**
+ * Visits the end of the annotation.
+ */
+ public void visitEnd() {
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationWriter.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationWriter.java
new file mode 100644
index 0000000..638711a
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/AnnotationWriter.java
@@ -0,0 +1,371 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * An {@link AnnotationVisitor} that generates annotations in bytecode form.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+final class AnnotationWriter extends AnnotationVisitor {
+
+ /**
+ * The class writer to which this annotation must be added.
+ */
+ private final ClassWriter cw;
+
+ /**
+ * The number of values in this annotation.
+ */
+ private int size;
+
+ /**
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation
+ * writers used for annotation default and annotation arrays use unnamed
+ * values.
+ */
+ private final boolean named;
+
+ /**
+ * The annotation values in bytecode form. This byte vector only contains
+ * the values themselves, i.e. the number of values must be stored as a
+ * unsigned short just before these bytes.
+ */
+ private final ByteVector bv;
+
+ /**
+ * The byte vector to be used to store the number of values of this
+ * annotation. See {@link #bv}.
+ */
+ private final ByteVector parent;
+
+ /**
+ * Where the number of values of this annotation must be stored in
+ * {@link #parent}.
+ */
+ private final int offset;
+
+ /**
+ * Next annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter next;
+
+ /**
+ * Previous annotation writer. This field is used to store annotation lists.
+ */
+ AnnotationWriter prev;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link AnnotationWriter}.
+ *
+ * @param cw
+ * the class writer to which this annotation must be added.
+ * @param named
+ * <tt>true<tt> if values are named, <tt>false</tt> otherwise.
+ * @param bv
+ * where the annotation values must be stored.
+ * @param parent
+ * where the number of annotation values must be stored.
+ * @param offset
+ * where in <tt>parent</tt> the number of annotation values must
+ * be stored.
+ */
+ AnnotationWriter(final ClassWriter cw, final boolean named,
+ final ByteVector bv, final ByteVector parent, final int offset) {
+ super(Opcodes.ASM5);
+ this.cw = cw;
+ this.named = named;
+ this.bv = bv;
+ this.parent = parent;
+ this.offset = offset;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the AnnotationVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visit(final String name, final Object value) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ if (value instanceof String) {
+ bv.put12('s', cw.newUTF8((String) value));
+ } else if (value instanceof Byte) {
+ bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);
+ } else if (value instanceof Boolean) {
+ int v = ((Boolean) value).booleanValue() ? 1 : 0;
+ bv.put12('Z', cw.newInteger(v).index);
+ } else if (value instanceof Character) {
+ bv.put12('C', cw.newInteger(((Character) value).charValue()).index);
+ } else if (value instanceof Short) {
+ bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);
+ } else if (value instanceof Type) {
+ bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));
+ } else if (value instanceof byte[]) {
+ byte[] v = (byte[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('B', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof boolean[]) {
+ boolean[] v = (boolean[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);
+ }
+ } else if (value instanceof short[]) {
+ short[] v = (short[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('S', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof char[]) {
+ char[] v = (char[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('C', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof int[]) {
+ int[] v = (int[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('I', cw.newInteger(v[i]).index);
+ }
+ } else if (value instanceof long[]) {
+ long[] v = (long[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('J', cw.newLong(v[i]).index);
+ }
+ } else if (value instanceof float[]) {
+ float[] v = (float[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('F', cw.newFloat(v[i]).index);
+ }
+ } else if (value instanceof double[]) {
+ double[] v = (double[]) value;
+ bv.put12('[', v.length);
+ for (int i = 0; i < v.length; i++) {
+ bv.put12('D', cw.newDouble(v[i]).index);
+ }
+ } else {
+ Item i = cw.newConstItem(value);
+ bv.put12(".s.IFJDCS".charAt(i.type), i.index);
+ }
+ }
+
+ @Override
+ public void visitEnum(final String name, final String desc,
+ final String value) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String name,
+ final String desc) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag and type, and reserve space for values count
+ bv.put12('@', cw.newUTF8(desc)).putShort(0);
+ return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);
+ }
+
+ @Override
+ public AnnotationVisitor visitArray(final String name) {
+ ++size;
+ if (named) {
+ bv.putShort(cw.newUTF8(name));
+ }
+ // write tag, and reserve space for array size
+ bv.put12('[', 0);
+ return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);
+ }
+
+ @Override
+ public void visitEnd() {
+ if (parent != null) {
+ byte[] data = parent.data;
+ data[offset] = (byte) (size >>> 8);
+ data[offset + 1] = (byte) size;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of this annotation writer list.
+ *
+ * @return the size of this annotation writer list.
+ */
+ int getSize() {
+ int size = 0;
+ AnnotationWriter aw = this;
+ while (aw != null) {
+ size += aw.bv.length;
+ aw = aw.next;
+ }
+ return size;
+ }
+
+ /**
+ * Puts the annotations of this annotation writer list into the given byte
+ * vector.
+ *
+ * @param out
+ * where the annotations must be put.
+ */
+ void put(final ByteVector out) {
+ int n = 0;
+ int size = 2;
+ AnnotationWriter aw = this;
+ AnnotationWriter last = null;
+ while (aw != null) {
+ ++n;
+ size += aw.bv.length;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putInt(size);
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+
+ /**
+ * Puts the given annotation lists into the given byte vector.
+ *
+ * @param panns
+ * an array of annotation writer lists.
+ * @param off
+ * index of the first annotation to be written.
+ * @param out
+ * where the annotations must be put.
+ */
+ static void put(final AnnotationWriter[] panns, final int off,
+ final ByteVector out) {
+ int size = 1 + 2 * (panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ out.putInt(size).putByte(panns.length - off);
+ for (int i = off; i < panns.length; ++i) {
+ AnnotationWriter aw = panns[i];
+ AnnotationWriter last = null;
+ int n = 0;
+ while (aw != null) {
+ ++n;
+ aw.visitEnd(); // in case user forgot to call visitEnd
+ aw.prev = last;
+ last = aw;
+ aw = aw.next;
+ }
+ out.putShort(n);
+ aw = last;
+ while (aw != null) {
+ out.putByteArray(aw.bv.data, 0, aw.bv.length);
+ aw = aw.prev;
+ }
+ }
+ }
+
+ /**
+ * Puts the given type reference and type path into the given bytevector.
+ * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.
+ *
+ * @param typeRef
+ * a reference to the annotated type. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param out
+ * where the type reference and type path must be put.
+ */
+ static void putTarget(int typeRef, TypePath typePath, ByteVector out) {
+ switch (typeRef >>> 24) {
+ case 0x00: // CLASS_TYPE_PARAMETER
+ case 0x01: // METHOD_TYPE_PARAMETER
+ case 0x16: // METHOD_FORMAL_PARAMETER
+ out.putShort(typeRef >>> 16);
+ break;
+ case 0x13: // FIELD
+ case 0x14: // METHOD_RETURN
+ case 0x15: // METHOD_RECEIVER
+ out.putByte(typeRef >>> 24);
+ break;
+ case 0x47: // CAST
+ case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+ case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+ out.putInt(typeRef);
+ break;
+ // case 0x10: // CLASS_EXTENDS
+ // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+ // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+ // case 0x17: // THROWS
+ // case 0x42: // EXCEPTION_PARAMETER
+ // case 0x43: // INSTANCEOF
+ // case 0x44: // NEW
+ // case 0x45: // CONSTRUCTOR_REFERENCE
+ // case 0x46: // METHOD_REFERENCE
+ default:
+ out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);
+ break;
+ }
+ if (typePath == null) {
+ out.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ out.putByteArray(typePath.b, typePath.offset, length);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Attribute.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Attribute.java
new file mode 100644
index 0000000..c339d30
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Attribute.java
@@ -0,0 +1,255 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A non standard class, field, method or code attribute.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class Attribute {
+
+ /**
+ * The type of this attribute.
+ */
+ public final String type;
+
+ /**
+ * The raw value of this attribute, used only for unknown attributes.
+ */
+ byte[] value;
+
+ /**
+ * The next attribute in this attribute list. May be <tt>null</tt>.
+ */
+ Attribute next;
+
+ /**
+ * Constructs a new empty attribute.
+ *
+ * @param type
+ * the type of the attribute.
+ */
+ protected Attribute(final String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is unknown. The default
+ * implementation of this method always returns <tt>true</tt>.
+ *
+ * @return <tt>true</tt> if this type of attribute is unknown.
+ */
+ public boolean isUnknown() {
+ return true;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this type of attribute is a code attribute.
+ *
+ * @return <tt>true</tt> if this type of attribute is a code attribute.
+ */
+ public boolean isCodeAttribute() {
+ return false;
+ }
+
+ /**
+ * Returns the labels corresponding to this attribute.
+ *
+ * @return the labels corresponding to this attribute, or <tt>null</tt> if
+ * this attribute is not a code attribute that contains labels.
+ */
+ protected Label[] getLabels() {
+ return null;
+ }
+
+ /**
+ * Reads a {@link #type type} attribute. This method must return a
+ * <i>new</i> {@link Attribute} object, of type {@link #type type},
+ * corresponding to the <tt>len</tt> bytes starting at the given offset, in
+ * the given class reader.
+ *
+ * @param cr
+ * the class that contains the attribute to be read.
+ * @param off
+ * index of the first byte of the attribute's content in
+ * {@link ClassReader#b cr.b}. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param len
+ * the length of the attribute's content.
+ * @param buf
+ * buffer to be used to call {@link ClassReader#readUTF8
+ * readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}
+ * or {@link ClassReader#readConst readConst}.
+ * @param codeOff
+ * index of the first byte of code's attribute content in
+ * {@link ClassReader#b cr.b}, or -1 if the attribute to be read
+ * is not a code attribute. The 6 attribute header bytes,
+ * containing the type and the length of the attribute, are not
+ * taken into account here.
+ * @param labels
+ * the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return a <i>new</i> {@link Attribute} object corresponding to the given
+ * bytes.
+ */
+ protected Attribute read(final ClassReader cr, final int off,
+ final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
+ Attribute attr = new Attribute(type);
+ attr.value = new byte[len];
+ System.arraycopy(cr.b, off, attr.value, 0, len);
+ return attr;
+ }
+
+ /**
+ * Returns the byte array form of this attribute.
+ *
+ * @param cw
+ * the class to which this attribute must be added. This
+ * parameter can be used to add to the constant pool of this
+ * class the items that corresponds to this attribute.
+ * @param code
+ * the bytecode of the method corresponding to this code
+ * attribute, or <tt>null</tt> if this attribute is not a code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to this
+ * code attribute, or <tt>null</tt> if this attribute is not a
+ * code attribute.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to this
+ * code attribute, or -1 if this attribute is not a code
+ * attribute.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to this code attribute, or -1 if this attribute
+ * is not a code attribute.
+ * @return the byte array form of this attribute.
+ */
+ protected ByteVector write(final ClassWriter cw, final byte[] code,
+ final int len, final int maxStack, final int maxLocals) {
+ ByteVector v = new ByteVector();
+ v.data = value;
+ v.length = value.length;
+ return v;
+ }
+
+ /**
+ * Returns the length of the attribute list that begins with this attribute.
+ *
+ * @return the length of the attribute list that begins with this attribute.
+ */
+ final int getCount() {
+ int count = 0;
+ Attribute attr = this;
+ while (attr != null) {
+ count += 1;
+ attr = attr.next;
+ }
+ return count;
+ }
+
+ /**
+ * Returns the size of all the attributes in this attribute list.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
+ * @return the size of all the attributes in this attribute list. This size
+ * includes the size of the attribute headers.
+ */
+ final int getSize(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals) {
+ Attribute attr = this;
+ int size = 0;
+ while (attr != null) {
+ cw.newUTF8(attr.type);
+ size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;
+ attr = attr.next;
+ }
+ return size;
+ }
+
+ /**
+ * Writes all the attributes of this attribute list in the given byte
+ * vector.
+ *
+ * @param cw
+ * the class writer to be used to convert the attributes into
+ * byte arrays, with the {@link #write write} method.
+ * @param code
+ * the bytecode of the method corresponding to these code
+ * attributes, or <tt>null</tt> if these attributes are not code
+ * attributes.
+ * @param len
+ * the length of the bytecode of the method corresponding to
+ * these code attributes, or <tt>null</tt> if these attributes
+ * are not code attributes.
+ * @param maxStack
+ * the maximum stack size of the method corresponding to these
+ * code attributes, or -1 if these attributes are not code
+ * attributes.
+ * @param maxLocals
+ * the maximum number of local variables of the method
+ * corresponding to these code attributes, or -1 if these
+ * attributes are not code attributes.
+ * @param out
+ * where the attributes must be written.
+ */
+ final void put(final ClassWriter cw, final byte[] code, final int len,
+ final int maxStack, final int maxLocals, final ByteVector out) {
+ Attribute attr = this;
+ while (attr != null) {
+ ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);
+ out.putShort(cw.newUTF8(attr.type)).putInt(b.length);
+ out.putByteArray(b.data, 0, b.length);
+ attr = attr.next;
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ByteVector.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ByteVector.java
new file mode 100644
index 0000000..181e973
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ByteVector.java
@@ -0,0 +1,339 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A dynamically extensible vector of bytes. This class is roughly equivalent to
+ * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.
+ *
+ * @author Eric Bruneton
+ */
+public class ByteVector {
+
+ /**
+ * The content of this vector.
+ */
+ byte[] data;
+
+ /**
+ * Actual number of bytes in this vector.
+ */
+ int length;
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with a default initial
+ * size.
+ */
+ public ByteVector() {
+ data = new byte[64];
+ }
+
+ /**
+ * Constructs a new {@link ByteVector ByteVector} with the given initial
+ * size.
+ *
+ * @param initialSize
+ * the initial size of the byte vector to be constructed.
+ */
+ public ByteVector(final int initialSize) {
+ data = new byte[initialSize];
+ }
+
+ /**
+ * Puts a byte into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b
+ * a byte.
+ * @return this byte vector.
+ */
+ public ByteVector putByte(final int b) {
+ int length = this.length;
+ if (length + 1 > data.length) {
+ enlarge(1);
+ }
+ data[length++] = (byte) b;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts two bytes into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
+ * @return this byte vector.
+ */
+ ByteVector put11(final int b1, final int b2) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b1;
+ data[length++] = (byte) b2;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a short into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param s
+ * a short.
+ * @return this byte vector.
+ */
+ public ByteVector putShort(final int s) {
+ int length = this.length;
+ if (length + 2 > data.length) {
+ enlarge(2);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a byte and a short into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b
+ * a byte.
+ * @param s
+ * a short.
+ * @return this byte vector.
+ */
+ ByteVector put12(final int b, final int s) {
+ int length = this.length;
+ if (length + 3 > data.length) {
+ enlarge(3);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) b;
+ data[length++] = (byte) (s >>> 8);
+ data[length++] = (byte) s;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an int into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param i
+ * an int.
+ * @return this byte vector.
+ */
+ public ByteVector putInt(final int i) {
+ int length = this.length;
+ if (length + 4 > data.length) {
+ enlarge(4);
+ }
+ byte[] data = this.data;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts a long into this byte vector. The byte vector is automatically
+ * enlarged if necessary.
+ *
+ * @param l
+ * a long.
+ * @return this byte vector.
+ */
+ public ByteVector putLong(final long l) {
+ int length = this.length;
+ if (length + 8 > data.length) {
+ enlarge(8);
+ }
+ byte[] data = this.data;
+ int i = (int) (l >>> 32);
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ i = (int) l;
+ data[length++] = (byte) (i >>> 24);
+ data[length++] = (byte) (i >>> 16);
+ data[length++] = (byte) (i >>> 8);
+ data[length++] = (byte) i;
+ this.length = length;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param s
+ * a String whose UTF8 encoded length must be less than 65536.
+ * @return this byte vector.
+ */
+ public ByteVector putUTF8(final String s) {
+ int charLength = s.length();
+ if (charLength > 65535) {
+ throw new IllegalArgumentException();
+ }
+ int len = length;
+ if (len + 2 + charLength > data.length) {
+ enlarge(2 + charLength);
+ }
+ byte[] data = this.data;
+ // optimistic algorithm: instead of computing the byte length and then
+ // serializing the string (which requires two loops), we assume the byte
+ // length is equal to char length (which is the most frequent case), and
+ // we start serializing the string right away. During the serialization,
+ // if we find that this assumption is wrong, we continue with the
+ // general method.
+ data[len++] = (byte) (charLength >>> 8);
+ data[len++] = (byte) charLength;
+ for (int i = 0; i < charLength; ++i) {
+ char c = s.charAt(i);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else {
+ length = len;
+ return encodeUTF8(s, i, 65535);
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an UTF8 string into this byte vector. The byte vector is
+ * automatically enlarged if necessary. The string length is encoded in two
+ * bytes before the encoded characters, if there is space for that (i.e. if
+ * this.length - i - 2 >= 0).
+ *
+ * @param s
+ * the String to encode.
+ * @param i
+ * the index of the first character to encode. The previous
+ * characters are supposed to have already been encoded, using
+ * only one byte per character.
+ * @param maxByteLength
+ * the maximum byte length of the encoded string, including the
+ * already encoded characters.
+ * @return this byte vector.
+ */
+ ByteVector encodeUTF8(final String s, int i, int maxByteLength) {
+ int charLength = s.length();
+ int byteLength = i;
+ char c;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ byteLength++;
+ } else if (c > '\u07FF') {
+ byteLength += 3;
+ } else {
+ byteLength += 2;
+ }
+ }
+ if (byteLength > maxByteLength) {
+ throw new IllegalArgumentException();
+ }
+ int start = length - i - 2;
+ if (start >= 0) {
+ data[start] = (byte) (byteLength >>> 8);
+ data[start + 1] = (byte) byteLength;
+ }
+ if (length + byteLength - i > data.length) {
+ enlarge(byteLength - i);
+ }
+ int len = length;
+ for (int j = i; j < charLength; ++j) {
+ c = s.charAt(j);
+ if (c >= '\001' && c <= '\177') {
+ data[len++] = (byte) c;
+ } else if (c > '\u07FF') {
+ data[len++] = (byte) (0xE0 | c >> 12 & 0xF);
+ data[len++] = (byte) (0x80 | c >> 6 & 0x3F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ } else {
+ data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);
+ data[len++] = (byte) (0x80 | c & 0x3F);
+ }
+ }
+ length = len;
+ return this;
+ }
+
+ /**
+ * Puts an array of bytes into this byte vector. The byte vector is
+ * automatically enlarged if necessary.
+ *
+ * @param b
+ * an array of bytes. May be <tt>null</tt> to put <tt>len</tt>
+ * null bytes into this byte vector.
+ * @param off
+ * index of the fist byte of b that must be copied.
+ * @param len
+ * number of bytes of b that must be copied.
+ * @return this byte vector.
+ */
+ public ByteVector putByteArray(final byte[] b, final int off, final int len) {
+ if (length + len > data.length) {
+ enlarge(len);
+ }
+ if (b != null) {
+ System.arraycopy(b, off, data, length, len);
+ }
+ length += len;
+ return this;
+ }
+
+ /**
+ * Enlarge this byte vector so that it can receive n more bytes.
+ *
+ * @param size
+ * number of additional bytes that this byte vector should be
+ * able to receive.
+ */
+ private void enlarge(final int size) {
+ int length1 = 2 * data.length;
+ int length2 = length + size;
+ byte[] newData = new byte[length1 > length2 ? length1 : length2];
+ System.arraycopy(data, 0, newData, 0, length);
+ data = newData;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassReader.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassReader.java
new file mode 100644
index 0000000..b4f1d29
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassReader.java
@@ -0,0 +1,2506 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * A Java class parser to make a {@link ClassVisitor} visit an existing class.
+ * This class parses a byte array conforming to the Java class file format and
+ * calls the appropriate visit methods of a given class visitor for each field,
+ * method and bytecode instruction encountered.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public class ClassReader {
+
+ /**
+ * True to enable signatures support.
+ */
+ static final boolean SIGNATURES = true;
+
+ /**
+ * True to enable annotations support.
+ */
+ static final boolean ANNOTATIONS = true;
+
+ /**
+ * True to enable stack map frames support.
+ */
+ static final boolean FRAMES = true;
+
+ /**
+ * True to enable bytecode writing support.
+ */
+ static final boolean WRITER = true;
+
+ /**
+ * True to enable JSR_W and GOTO_W support.
+ */
+ static final boolean RESIZE = true;
+
+ /**
+ * Flag to skip method code. If this class is set <code>CODE</code>
+ * attribute won't be visited. This can be used, for example, to retrieve
+ * annotations for methods and method parameters.
+ */
+ public static final int SKIP_CODE = 1;
+
+ /**
+ * Flag to skip the debug information in the class. If this flag is set the
+ * debug information of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and
+ * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be
+ * called.
+ */
+ public static final int SKIP_DEBUG = 2;
+
+ /**
+ * Flag to skip the stack map frames in the class. If this flag is set the
+ * stack map frames of the class is not visited, i.e. the
+ * {@link MethodVisitor#visitFrame visitFrame} method will not be called.
+ * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is
+ * used: it avoids visiting frames that will be ignored and recomputed from
+ * scratch in the class writer.
+ */
+ public static final int SKIP_FRAMES = 4;
+
+ /**
+ * Flag to expand the stack map frames. By default stack map frames are
+ * visited in their original format (i.e. "expanded" for classes whose
+ * version is less than V1_6, and "compressed" for the other classes). If
+ * this flag is set, stack map frames are always visited in expanded format
+ * (this option adds a decompression/recompression step in ClassReader and
+ * ClassWriter which degrades performances quite a lot).
+ */
+ public static final int EXPAND_FRAMES = 8;
+
+ /**
+ * The class to be parsed. <i>The content of this array must not be
+ * modified. This field is intended for {@link Attribute} sub classes, and
+ * is normally not needed by class generators or adapters.</i>
+ */
+ public final byte[] b;
+
+ /**
+ * The start index of each constant pool item in {@link #b b}, plus one. The
+ * one byte offset skips the constant pool item tag that indicates its type.
+ */
+ private final int[] items;
+
+ /**
+ * The String objects corresponding to the CONSTANT_Utf8 items. This cache
+ * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,
+ * which GREATLY improves performances (by a factor 2 to 3). This caching
+ * strategy could be extended to all constant pool items, but its benefit
+ * would not be so great for these items (because they are much less
+ * expensive to parse than CONSTANT_Utf8 items).
+ */
+ private final String[] strings;
+
+ /**
+ * Maximum length of the strings contained in the constant pool of the
+ * class.
+ */
+ private final int maxStringLength;
+
+ /**
+ * Start index of the class header information (access, name...) in
+ * {@link #b b}.
+ */
+ public final int header;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b
+ * the bytecode of the class to be read.
+ */
+ public ClassReader(final byte[] b) {
+ this(b, 0, b.length);
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param b
+ * the bytecode of the class to be read.
+ * @param off
+ * the start offset of the class data.
+ * @param len
+ * the length of the class data.
+ */
+ public ClassReader(final byte[] b, final int off, final int len) {
+ this.b = b;
+ // checks the class version
+ if (readShort(off + 6) > Opcodes.V1_8) {
+ throw new IllegalArgumentException();
+ }
+ // parses the constant pool
+ items = new int[readUnsignedShort(off + 8)];
+ int n = items.length;
+ strings = new String[n];
+ int max = 0;
+ int index = off + 10;
+ for (int i = 1; i < n; ++i) {
+ items[i] = index + 1;
+ int size;
+ switch (b[index]) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ case ClassWriter.NAME_TYPE:
+ case ClassWriter.INDY:
+ size = 5;
+ break;
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ size = 9;
+ ++i;
+ break;
+ case ClassWriter.UTF8:
+ size = 3 + readUnsignedShort(index + 1);
+ if (size > max) {
+ max = size;
+ }
+ break;
+ case ClassWriter.HANDLE:
+ size = 4;
+ break;
+ // case ClassWriter.CLASS:
+ // case ClassWriter.STR:
+ // case ClassWriter.MTYPE
+ default:
+ size = 3;
+ break;
+ }
+ index += size;
+ }
+ maxStringLength = max;
+ // the class header information starts just after the constant pool
+ header = index;
+ }
+
+ /**
+ * Returns the class's access flags (see {@link Opcodes}). This value may
+ * not reflect Deprecated and Synthetic flags when bytecode is before 1.5
+ * and those flags are represented by attributes.
+ *
+ * @return the class access flags
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public int getAccess() {
+ return readUnsignedShort(header);
+ }
+
+ /**
+ * Returns the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the internal class name
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getClassName() {
+ return readClass(header + 2, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For interfaces, the
+ * super class is {@link Object}.
+ *
+ * @return the internal name of super class, or <tt>null</tt> for
+ * {@link Object} class.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String getSuperName() {
+ return readClass(header + 4, new char[maxStringLength]);
+ }
+
+ /**
+ * Returns the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}).
+ *
+ * @return the array of internal names for all implemented interfaces or
+ * <tt>null</tt>.
+ *
+ * @see ClassVisitor#visit(int, int, String, String, String, String[])
+ */
+ public String[] getInterfaces() {
+ int index = header + 6;
+ int n = readUnsignedShort(index);
+ String[] interfaces = new String[n];
+ if (n > 0) {
+ char[] buf = new char[maxStringLength];
+ for (int i = 0; i < n; ++i) {
+ index += 2;
+ interfaces[i] = readClass(index, buf);
+ }
+ }
+ return interfaces;
+ }
+
+ /**
+ * Copies the constant pool data into the given {@link ClassWriter}. Should
+ * be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy constant pool into.
+ */
+ void copyPool(final ClassWriter classWriter) {
+ char[] buf = new char[maxStringLength];
+ int ll = items.length;
+ Item[] items2 = new Item[ll];
+ for (int i = 1; i < ll; i++) {
+ int index = items[i];
+ int tag = b[index - 1];
+ Item item = new Item(i);
+ int nameType;
+ switch (tag) {
+ case ClassWriter.FIELD:
+ case ClassWriter.METH:
+ case ClassWriter.IMETH:
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(tag, readClass(index, buf), readUTF8(nameType, buf),
+ readUTF8(nameType + 2, buf));
+ break;
+ case ClassWriter.INT:
+ item.set(readInt(index));
+ break;
+ case ClassWriter.FLOAT:
+ item.set(Float.intBitsToFloat(readInt(index)));
+ break;
+ case ClassWriter.NAME_TYPE:
+ item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),
+ null);
+ break;
+ case ClassWriter.LONG:
+ item.set(readLong(index));
+ ++i;
+ break;
+ case ClassWriter.DOUBLE:
+ item.set(Double.longBitsToDouble(readLong(index)));
+ ++i;
+ break;
+ case ClassWriter.UTF8: {
+ String s = strings[i];
+ if (s == null) {
+ index = items[i];
+ s = strings[i] = readUTF(index + 2,
+ readUnsignedShort(index), buf);
+ }
+ item.set(tag, s, null, null);
+ break;
+ }
+ case ClassWriter.HANDLE: {
+ int fieldOrMethodRef = items[readUnsignedShort(index + 1)];
+ nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];
+ item.set(ClassWriter.HANDLE_BASE + readByte(index),
+ readClass(fieldOrMethodRef, buf),
+ readUTF8(nameType, buf), readUTF8(nameType + 2, buf));
+ break;
+ }
+ case ClassWriter.INDY:
+ if (classWriter.bootstrapMethods == null) {
+ copyBootstrapMethods(classWriter, items2, buf);
+ }
+ nameType = items[readUnsignedShort(index + 2)];
+ item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),
+ readUnsignedShort(index));
+ break;
+ // case ClassWriter.STR:
+ // case ClassWriter.CLASS:
+ // case ClassWriter.MTYPE
+ default:
+ item.set(tag, readUTF8(index, buf), null, null);
+ break;
+ }
+
+ int index2 = item.hashCode % items2.length;
+ item.next = items2[index2];
+ items2[index2] = item;
+ }
+
+ int off = items[1] - 1;
+ classWriter.pool.putByteArray(b, off, header - off);
+ classWriter.items = items2;
+ classWriter.threshold = (int) (0.75d * ll);
+ classWriter.index = ll;
+ }
+
+ /**
+ * Copies the bootstrap method data into the given {@link ClassWriter}.
+ * Should be called before the {@link #accept(ClassVisitor,int)} method.
+ *
+ * @param classWriter
+ * the {@link ClassWriter} to copy bootstrap methods into.
+ */
+ private void copyBootstrapMethods(final ClassWriter classWriter,
+ final Item[] items, final char[] c) {
+ // finds the "BootstrapMethods" attribute
+ int u = getAttributes();
+ boolean found = false;
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("BootstrapMethods".equals(attrName)) {
+ found = true;
+ break;
+ }
+ u += 6 + readInt(u + 4);
+ }
+ if (!found) {
+ return;
+ }
+ // copies the bootstrap methods in the class writer
+ int boostrapMethodCount = readUnsignedShort(u + 8);
+ for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {
+ int position = v - u - 10;
+ int hashCode = readConst(readUnsignedShort(v), c).hashCode();
+ for (int k = readUnsignedShort(v + 2); k > 0; --k) {
+ hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();
+ v += 2;
+ }
+ v += 4;
+ Item item = new Item(j);
+ item.set(position, hashCode & 0x7FFFFFFF);
+ int index = item.hashCode % items.length;
+ item.next = items[index];
+ items[index] = item;
+ }
+ int attrSize = readInt(u + 4);
+ ByteVector bootstrapMethods = new ByteVector(attrSize + 62);
+ bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);
+ classWriter.bootstrapMethodsCount = boostrapMethodCount;
+ classWriter.bootstrapMethods = bootstrapMethods;
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @throws IOException
+ * if a problem occurs during reading.
+ */
+ public ClassReader(final InputStream is) throws IOException {
+ this(readClass(is, false));
+ }
+
+ /**
+ * Constructs a new {@link ClassReader} object.
+ *
+ * @param name
+ * the binary qualified name of the class to be read.
+ * @throws IOException
+ * if an exception occurs during reading.
+ */
+ public ClassReader(final String name) throws IOException {
+ this(readClass(
+ ClassLoader.getSystemResourceAsStream(name.replace('.', '/')
+ + ".class"), true));
+ }
+
+ /**
+ * Reads the bytecode of a class.
+ *
+ * @param is
+ * an input stream from which to read the class.
+ * @param close
+ * true to close the input stream after reading.
+ * @return the bytecode read from the given input stream.
+ * @throws IOException
+ * if a problem occurs during reading.
+ */
+ private static byte[] readClass(final InputStream is, boolean close)
+ throws IOException {
+ if (is == null) {
+ throw new IOException("Class not found");
+ }
+ try {
+ byte[] b = new byte[is.available()];
+ int len = 0;
+ while (true) {
+ int n = is.read(b, len, b.length - len);
+ if (n == -1) {
+ if (len < b.length) {
+ byte[] c = new byte[len];
+ System.arraycopy(b, 0, c, 0, len);
+ b = c;
+ }
+ return b;
+ }
+ len += n;
+ if (len == b.length) {
+ int last = is.read();
+ if (last < 0) {
+ return b;
+ }
+ byte[] c = new byte[b.length + 1000];
+ System.arraycopy(b, 0, c, 0, len);
+ c[len++] = (byte) last;
+ b = c;
+ }
+ }
+ } finally {
+ if (close) {
+ is.close();
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}
+ * . This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor, final int flags) {
+ accept(classVisitor, new Attribute[0], flags);
+ }
+
+ /**
+ * Makes the given visitor visit the Java class of this {@link ClassReader}.
+ * This class is the one specified in the constructor (see
+ * {@link #ClassReader(byte[]) ClassReader}).
+ *
+ * @param classVisitor
+ * the visitor that must visit this class.
+ * @param attrs
+ * prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to
+ * the type of one the prototypes will not be parsed: its byte
+ * array value will be passed unchanged to the ClassWriter.
+ * <i>This may corrupt it if this value contains references to
+ * the constant pool, or has syntactic or semantic links with a
+ * class element that has been transformed by a class adapter
+ * between the reader and the writer</i>.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}
+ * , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.
+ */
+ public void accept(final ClassVisitor classVisitor,
+ final Attribute[] attrs, final int flags) {
+ int u = header; // current offset in the class file
+ char[] c = new char[maxStringLength]; // buffer used to read strings
+
+ Context context = new Context();
+ context.attrs = attrs;
+ context.flags = flags;
+ context.buffer = c;
+
+ // reads the class declaration
+ int access = readUnsignedShort(u);
+ String name = readClass(u + 2, c);
+ String superClass = readClass(u + 4, c);
+ String[] interfaces = new String[readUnsignedShort(u + 6)];
+ u += 8;
+ for (int i = 0; i < interfaces.length; ++i) {
+ interfaces[i] = readClass(u, c);
+ u += 2;
+ }
+
+ // reads the class attributes
+ String signature = null;
+ String sourceFile = null;
+ String sourceDebug = null;
+ String enclosingOwner = null;
+ String enclosingName = null;
+ String enclosingDesc = null;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int innerClasses = 0;
+ Attribute attributes = null;
+
+ u = getAttributes();
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("SourceFile".equals(attrName)) {
+ sourceFile = readUTF8(u + 8, c);
+ } else if ("InnerClasses".equals(attrName)) {
+ innerClasses = u + 8;
+ } else if ("EnclosingMethod".equals(attrName)) {
+ enclosingOwner = readClass(u + 8, c);
+ int item = readUnsignedShort(u + 10);
+ if (item != 0) {
+ enclosingName = readUTF8(items[item], c);
+ enclosingDesc = readUTF8(items[item] + 2, c);
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if ("SourceDebugExtension".equals(attrName)) {
+ int len = readInt(u + 4);
+ sourceDebug = readUTF(u + 8, len, new char[len]);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else if ("BootstrapMethods".equals(attrName)) {
+ int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];
+ for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {
+ bootstrapMethods[j] = v;
+ v += 2 + readUnsignedShort(v + 2) << 1;
+ }
+ context.bootstrapMethods = bootstrapMethods;
+ } else {
+ Attribute attr = readAttribute(attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
+ }
+ }
+ u += 6 + readInt(u + 4);
+ }
+
+ // visits the class declaration
+ classVisitor.visit(readInt(items[1] - 7), access, name, signature,
+ superClass, interfaces);
+
+ // visits the source and debug info
+ if ((flags & SKIP_DEBUG) == 0
+ && (sourceFile != null || sourceDebug != null)) {
+ classVisitor.visitSource(sourceFile, sourceDebug);
+ }
+
+ // visits the outer class
+ if (enclosingOwner != null) {
+ classVisitor.visitOuterClass(enclosingOwner, enclosingName,
+ enclosingDesc);
+ }
+
+ // visits the class annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ classVisitor.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ }
+
+ // visits the attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ classVisitor.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the inner classes
+ if (innerClasses != 0) {
+ int v = innerClasses + 2;
+ for (int i = readUnsignedShort(innerClasses); i > 0; --i) {
+ classVisitor.visitInnerClass(readClass(v, c),
+ readClass(v + 2, c), readUTF8(v + 4, c),
+ readUnsignedShort(v + 6));
+ v += 8;
+ }
+ }
+
+ // visits the fields and methods
+ u = header + 10 + 2 * interfaces.length;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readField(classVisitor, context, u);
+ }
+ u += 2;
+ for (int i = readUnsignedShort(u - 2); i > 0; --i) {
+ u = readMethod(classVisitor, context, u);
+ }
+
+ // visits the end of the class
+ classVisitor.visitEnd();
+ }
+
+ /**
+ * Reads a field and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the field.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the field in the class file.
+ * @return the offset of the first byte following the field in the class.
+ */
+ private int readField(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the field declaration
+ char[] c = context.buffer;
+ int access = readUnsignedShort(u);
+ String name = readUTF8(u + 2, c);
+ String desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the field attributes
+ String signature = null;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ Object value = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("ConstantValue".equals(attrName)) {
+ int item = readUnsignedShort(u + 8);
+ value = item == 0 ? null : readConst(item, c);
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ access |= Opcodes.ACC_DEPRECATED;
+ } else if ("Synthetic".equals(attrName)) {
+ access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else {
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
+ }
+ }
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // visits the field declaration
+ FieldVisitor fv = classVisitor.visitField(access, name, desc,
+ signature, value);
+ if (fv == null) {
+ return u;
+ }
+
+ // visits the field annotations and type annotations
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ fv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ }
+
+ // visits the field attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ fv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the end of the field
+ fv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads a method and makes the given visitor visit it.
+ *
+ * @param classVisitor
+ * the visitor that must visit the method.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the method in the class file.
+ * @return the offset of the first byte following the method in the class.
+ */
+ private int readMethod(final ClassVisitor classVisitor,
+ final Context context, int u) {
+ // reads the method declaration
+ char[] c = context.buffer;
+ context.access = readUnsignedShort(u);
+ context.name = readUTF8(u + 2, c);
+ context.desc = readUTF8(u + 4, c);
+ u += 6;
+
+ // reads the method attributes
+ int code = 0;
+ int exception = 0;
+ String[] exceptions = null;
+ String signature = null;
+ int methodParameters = 0;
+ int anns = 0;
+ int ianns = 0;
+ int tanns = 0;
+ int itanns = 0;
+ int dann = 0;
+ int mpanns = 0;
+ int impanns = 0;
+ int firstAttribute = u;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ // tests are sorted in decreasing frequency order
+ // (based on frequencies observed on typical classes)
+ if ("Code".equals(attrName)) {
+ if ((context.flags & SKIP_CODE) == 0) {
+ code = u + 8;
+ }
+ } else if ("Exceptions".equals(attrName)) {
+ exceptions = new String[readUnsignedShort(u + 8)];
+ exception = u + 10;
+ for (int j = 0; j < exceptions.length; ++j) {
+ exceptions[j] = readClass(exception, c);
+ exception += 2;
+ }
+ } else if (SIGNATURES && "Signature".equals(attrName)) {
+ signature = readUTF8(u + 8, c);
+ } else if ("Deprecated".equals(attrName)) {
+ context.access |= Opcodes.ACC_DEPRECATED;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleAnnotations".equals(attrName)) {
+ anns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = u + 8;
+ } else if (ANNOTATIONS && "AnnotationDefault".equals(attrName)) {
+ dann = u + 8;
+ } else if ("Synthetic".equals(attrName)) {
+ context.access |= Opcodes.ACC_SYNTHETIC
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleAnnotations".equals(attrName)) {
+ ianns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleParameterAnnotations".equals(attrName)) {
+ mpanns = u + 8;
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleParameterAnnotations".equals(attrName)) {
+ impanns = u + 8;
+ } else if ("MethodParameters".equals(attrName)) {
+ methodParameters = u + 8;
+ } else {
+ Attribute attr = readAttribute(context.attrs, attrName, u + 8,
+ readInt(u + 4), c, -1, null);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
+ }
+ }
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // visits the method declaration
+ MethodVisitor mv = classVisitor.visitMethod(context.access,
+ context.name, context.desc, signature, exceptions);
+ if (mv == null) {
+ return u;
+ }
+
+ /*
+ * if the returned MethodVisitor is in fact a MethodWriter, it means
+ * there is no method adapter between the reader and the writer. If, in
+ * addition, the writer's constant pool was copied from this reader
+ * (mw.cw.cr == this), and the signature and exceptions of the method
+ * have not been changed, then it is possible to skip all visit events
+ * and just copy the original code of the method to the writer (the
+ * access, name and descriptor can have been changed, this is not
+ * important since they are not copied as is from the reader).
+ */
+ if (WRITER && mv instanceof MethodWriter) {
+ MethodWriter mw = (MethodWriter) mv;
+ if (mw.cw.cr == this && signature == mw.signature) {
+ boolean sameExceptions = false;
+ if (exceptions == null) {
+ sameExceptions = mw.exceptionCount == 0;
+ } else if (exceptions.length == mw.exceptionCount) {
+ sameExceptions = true;
+ for (int j = exceptions.length - 1; j >= 0; --j) {
+ exception -= 2;
+ if (mw.exceptions[j] != readUnsignedShort(exception)) {
+ sameExceptions = false;
+ break;
+ }
+ }
+ }
+ if (sameExceptions) {
+ /*
+ * we do not copy directly the code into MethodWriter to
+ * save a byte array copy operation. The real copy will be
+ * done in ClassWriter.toByteArray().
+ */
+ mw.classReaderOffset = firstAttribute;
+ mw.classReaderLength = u - firstAttribute;
+ return u;
+ }
+ }
+ }
+
+ // visit the method parameters
+ if (methodParameters != 0) {
+ for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {
+ mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));
+ }
+ }
+
+ // visits the method annotations
+ if (ANNOTATIONS && dann != 0) {
+ AnnotationVisitor dv = mv.visitAnnotationDefault();
+ readAnnotationValue(dann, c, null, dv);
+ if (dv != null) {
+ dv.visitEnd();
+ }
+ }
+ if (ANNOTATIONS && anns != 0) {
+ for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && ianns != 0) {
+ for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitAnnotation(readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && tanns != 0) {
+ for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ }
+ if (ANNOTATIONS && itanns != 0) {
+ for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {
+ v = readAnnotationTarget(context, v);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitTypeAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ }
+ if (ANNOTATIONS && mpanns != 0) {
+ readParameterAnnotations(mv, context, mpanns, true);
+ }
+ if (ANNOTATIONS && impanns != 0) {
+ readParameterAnnotations(mv, context, impanns, false);
+ }
+
+ // visits the method attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ mv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the method code
+ if (code != 0) {
+ mv.visitCode();
+ readCode(mv, context, code);
+ }
+
+ // visits the end of the method
+ mv.visitEnd();
+
+ return u;
+ }
+
+ /**
+ * Reads the bytecode of a method and makes the given visitor visit it.
+ *
+ * @param mv
+ * the visitor that must visit the method's code.
+ * @param context
+ * information about the class being parsed.
+ * @param u
+ * the start offset of the code attribute in the class file.
+ */
+ private void readCode(final MethodVisitor mv, final Context context, int u) {
+ // reads the header
+ byte[] b = this.b;
+ char[] c = context.buffer;
+ int maxStack = readUnsignedShort(u);
+ int maxLocals = readUnsignedShort(u + 2);
+ int codeLength = readInt(u + 4);
+ u += 8;
+
+ // reads the bytecode to find the labels
+ int codeStart = u;
+ int codeEnd = u + codeLength;
+ Label[] labels = context.labels = new Label[codeLength + 2];
+ readLabel(codeLength + 1, labels);
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ readLabel(offset + readShort(u + 1), labels);
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ readLabel(offset + readInt(u + 1), labels);
+ u += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 4;
+ }
+ u += 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ readLabel(offset + readInt(u), labels);
+ for (int i = readInt(u + 4); i > 0; --i) {
+ readLabel(offset + readInt(u + 12), labels);
+ u += 8;
+ }
+ u += 8;
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ u += 4;
+ break;
+ }
+ }
+
+ // reads the try catch entries to find the labels, and also visits them
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ Label start = readLabel(readUnsignedShort(u + 2), labels);
+ Label end = readLabel(readUnsignedShort(u + 4), labels);
+ Label handler = readLabel(readUnsignedShort(u + 6), labels);
+ String type = readUTF8(items[readUnsignedShort(u + 8)], c);
+ mv.visitTryCatchBlock(start, end, handler, type);
+ u += 8;
+ }
+ u += 2;
+
+ // reads the code attributes
+ int[] tanns = null; // start index of each visible type annotation
+ int[] itanns = null; // start index of each invisible type annotation
+ int tann = 0; // current index in tanns array
+ int itann = 0; // current index in itanns array
+ int ntoff = -1; // next visible type annotation code offset
+ int nitoff = -1; // next invisible type annotation code offset
+ int varTable = 0;
+ int varTypeTable = 0;
+ boolean zip = true;
+ boolean unzip = (context.flags & EXPAND_FRAMES) != 0;
+ int stackMap = 0;
+ int stackMapSize = 0;
+ int frameCount = 0;
+ Context frame = null;
+ Attribute attributes = null;
+
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ String attrName = readUTF8(u + 2, c);
+ if ("LocalVariableTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ varTable = u + 8;
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ label += readUnsignedShort(v + 12);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ v += 10;
+ }
+ }
+ } else if ("LocalVariableTypeTable".equals(attrName)) {
+ varTypeTable = u + 8;
+ } else if ("LineNumberTable".equals(attrName)) {
+ if ((context.flags & SKIP_DEBUG) == 0) {
+ for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {
+ int label = readUnsignedShort(v + 10);
+ if (labels[label] == null) {
+ readLabel(label, labels).status |= Label.DEBUG;
+ }
+ Label l = labels[label];
+ while (l.line > 0) {
+ if (l.next == null) {
+ l.next = new Label();
+ }
+ l = l.next;
+ }
+ l.line = readUnsignedShort(v + 12);
+ v += 4;
+ }
+ }
+ } else if (ANNOTATIONS
+ && "RuntimeVisibleTypeAnnotations".equals(attrName)) {
+ tanns = readTypeAnnotations(mv, context, u + 8, true);
+ ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1
+ : readUnsignedShort(tanns[0] + 1);
+ } else if (ANNOTATIONS
+ && "RuntimeInvisibleTypeAnnotations".equals(attrName)) {
+ itanns = readTypeAnnotations(mv, context, u + 8, false);
+ nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1
+ : readUnsignedShort(itanns[0] + 1);
+ } else if (FRAMES && "StackMapTable".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * here we do not extract the labels corresponding to the
+ * attribute content. This would require a full parsing of the
+ * attribute, which would need to be repeated in the second
+ * phase (see below). Instead the content of the attribute is
+ * read one frame at a time (i.e. after a frame has been
+ * visited, the next frame is read), and the labels it contains
+ * are also extracted one frame at a time. Thanks to the
+ * ordering of frames, having only a "one frame lookahead" is
+ * not a problem, i.e. it is not possible to see an offset
+ * smaller than the offset of the current insn and for which no
+ * Label exist.
+ */
+ /*
+ * This is not true for UNINITIALIZED type offsets. We solve
+ * this by parsing the stack map table without a full decoding
+ * (see below).
+ */
+ } else if (FRAMES && "StackMap".equals(attrName)) {
+ if ((context.flags & SKIP_FRAMES) == 0) {
+ zip = false;
+ stackMap = u + 10;
+ stackMapSize = readInt(u + 4);
+ frameCount = readUnsignedShort(u + 8);
+ }
+ /*
+ * IMPORTANT! here we assume that the frames are ordered, as in
+ * the StackMapTable attribute, although this is not guaranteed
+ * by the attribute format.
+ */
+ } else {
+ for (int j = 0; j < context.attrs.length; ++j) {
+ if (context.attrs[j].type.equals(attrName)) {
+ Attribute attr = context.attrs[j].read(this, u + 8,
+ readInt(u + 4), c, codeStart - 8, labels);
+ if (attr != null) {
+ attr.next = attributes;
+ attributes = attr;
+ }
+ }
+ }
+ }
+ u += 6 + readInt(u + 4);
+ }
+ u += 2;
+
+ // generates the first (implicit) stack map frame
+ if (FRAMES && stackMap != 0) {
+ /*
+ * for the first explicit frame the offset is not offset_delta + 1
+ * but only offset_delta; setting the implicit frame offset to -1
+ * allow the use of the "offset_delta + 1" rule in all cases
+ */
+ frame = context;
+ frame.offset = -1;
+ frame.mode = 0;
+ frame.localCount = 0;
+ frame.localDiff = 0;
+ frame.stackCount = 0;
+ frame.local = new Object[maxLocals];
+ frame.stack = new Object[maxStack];
+ if (unzip) {
+ getImplicitFrame(context);
+ }
+ /*
+ * Finds labels for UNINITIALIZED frame types. Instead of decoding
+ * each element of the stack map table, we look for 3 consecutive
+ * bytes that "look like" an UNINITIALIZED type (tag 8, offset
+ * within code bounds, NEW instruction at this offset). We may find
+ * false positives (i.e. not real UNINITIALIZED types), but this
+ * should be rare, and the only consequence will be the creation of
+ * an unneeded label. This is better than creating a label for each
+ * NEW instruction, and faster than fully decoding the whole stack
+ * map table.
+ */
+ for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {
+ if (b[i] == 8) { // UNINITIALIZED FRAME TYPE
+ int v = readUnsignedShort(i + 1);
+ if (v >= 0 && v < codeLength) {
+ if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {
+ readLabel(v, labels);
+ }
+ }
+ }
+ }
+ }
+
+ // visits the instructions
+ u = codeStart;
+ while (u < codeEnd) {
+ int offset = u - codeStart;
+
+ // visits the label and line number for this offset, if any
+ Label l = labels[offset];
+ if (l != null) {
+ Label next = l.next;
+ l.next = null;
+ mv.visitLabel(l);
+ if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {
+ mv.visitLineNumber(l.line, l);
+ while (next != null) {
+ mv.visitLineNumber(next.line, l);
+ next = next.next;
+ }
+ }
+ }
+
+ // visits the frame for this offset, if any
+ while (FRAMES && frame != null
+ && (frame.offset == offset || frame.offset == -1)) {
+ // if there is a frame for this offset, makes the visitor visit
+ // it, and reads the next frame if there is one.
+ if (frame.offset != -1) {
+ if (!zip || unzip) {
+ mv.visitFrame(Opcodes.F_NEW, frame.localCount,
+ frame.local, frame.stackCount, frame.stack);
+ } else {
+ mv.visitFrame(frame.mode, frame.localDiff, frame.local,
+ frame.stackCount, frame.stack);
+ }
+ }
+ if (frameCount > 0) {
+ stackMap = readFrame(stackMap, zip, unzip, frame);
+ --frameCount;
+ } else {
+ frame = null;
+ }
+ }
+
+ // visits the instruction at this offset
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ mv.visitInsn(opcode);
+ u += 1;
+ break;
+ case ClassWriter.IMPLVAR_INSN:
+ if (opcode > Opcodes.ISTORE) {
+ opcode -= 59; // ISTORE_0
+ mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),
+ opcode & 0x3);
+ } else {
+ opcode -= 26; // ILOAD_0
+ mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);
+ }
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);
+ u += 5;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));
+ u += 6;
+ } else {
+ mv.visitVarInsn(opcode, readUnsignedShort(u + 2));
+ u += 4;
+ }
+ break;
+ case ClassWriter.TABL_INSN: {
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ int label = offset + readInt(u);
+ int min = readInt(u + 4);
+ int max = readInt(u + 8);
+ Label[] table = new Label[max - min + 1];
+ u += 12;
+ for (int i = 0; i < table.length; ++i) {
+ table[i] = labels[offset + readInt(u)];
+ u += 4;
+ }
+ mv.visitTableSwitchInsn(min, max, labels[label], table);
+ break;
+ }
+ case ClassWriter.LOOK_INSN: {
+ // skips 0 to 3 padding bytes
+ u = u + 4 - (offset & 3);
+ // reads instruction
+ int label = offset + readInt(u);
+ int len = readInt(u + 4);
+ int[] keys = new int[len];
+ Label[] values = new Label[len];
+ u += 8;
+ for (int i = 0; i < len; ++i) {
+ keys[i] = readInt(u);
+ values[i] = labels[offset + readInt(u + 4)];
+ u += 8;
+ }
+ mv.visitLookupSwitchInsn(labels[label], keys, values);
+ break;
+ }
+ case ClassWriter.VAR_INSN:
+ mv.visitVarInsn(opcode, b[u + 1] & 0xFF);
+ u += 2;
+ break;
+ case ClassWriter.SBYTE_INSN:
+ mv.visitIntInsn(opcode, b[u + 1]);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ mv.visitIntInsn(opcode, readShort(u + 1));
+ u += 3;
+ break;
+ case ClassWriter.LDC_INSN:
+ mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c));
+ u += 2;
+ break;
+ case ClassWriter.LDCW_INSN:
+ mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));
+ u += 3;
+ break;
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.ITFMETH_INSN: {
+ int cpIndex = items[readUnsignedShort(u + 1)];
+ boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;
+ String iowner = readClass(cpIndex, c);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+ if (opcode < Opcodes.INVOKEVIRTUAL) {
+ mv.visitFieldInsn(opcode, iowner, iname, idesc);
+ } else {
+ mv.visitMethodInsn(opcode, iowner, iname, idesc, itf);
+ }
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ u += 5;
+ } else {
+ u += 3;
+ }
+ break;
+ }
+ case ClassWriter.INDYMETH_INSN: {
+ int cpIndex = items[readUnsignedShort(u + 1)];
+ int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];
+ Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);
+ int bsmArgCount = readUnsignedShort(bsmIndex + 2);
+ Object[] bsmArgs = new Object[bsmArgCount];
+ bsmIndex += 4;
+ for (int i = 0; i < bsmArgCount; i++) {
+ bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);
+ bsmIndex += 2;
+ }
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String iname = readUTF8(cpIndex, c);
+ String idesc = readUTF8(cpIndex + 2, c);
+ mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);
+ u += 5;
+ break;
+ }
+ case ClassWriter.TYPE_INSN:
+ mv.visitTypeInsn(opcode, readClass(u + 1, c));
+ u += 3;
+ break;
+ case ClassWriter.IINC_INSN:
+ mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]);
+ u += 3;
+ break;
+ // case MANA_INSN:
+ default:
+ mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF);
+ u += 4;
+ break;
+ }
+
+ // visit the instruction annotations, if any
+ while (tanns != null && tann < tanns.length && ntoff <= offset) {
+ if (ntoff == offset) {
+ int v = readAnnotationTarget(context, tanns[tann]);
+ readAnnotationValues(v + 2, c, true,
+ mv.visitInsnAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), true));
+ }
+ ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1
+ : readUnsignedShort(tanns[tann] + 1);
+ }
+ while (itanns != null && itann < itanns.length && nitoff <= offset) {
+ if (nitoff == offset) {
+ int v = readAnnotationTarget(context, itanns[itann]);
+ readAnnotationValues(v + 2, c, true,
+ mv.visitInsnAnnotation(context.typeRef,
+ context.typePath, readUTF8(v, c), false));
+ }
+ nitoff = ++itann >= itanns.length
+ || readByte(itanns[itann]) < 0x43 ? -1
+ : readUnsignedShort(itanns[itann] + 1);
+ }
+ }
+ if (labels[codeLength] != null) {
+ mv.visitLabel(labels[codeLength]);
+ }
+
+ // visits the local variable tables
+ if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) {
+ int[] typeTable = null;
+ if (varTypeTable != 0) {
+ u = varTypeTable + 2;
+ typeTable = new int[readUnsignedShort(varTypeTable) * 3];
+ for (int i = typeTable.length; i > 0;) {
+ typeTable[--i] = u + 6; // signature
+ typeTable[--i] = readUnsignedShort(u + 8); // index
+ typeTable[--i] = readUnsignedShort(u); // start
+ u += 10;
+ }
+ }
+ u = varTable + 2;
+ for (int i = readUnsignedShort(varTable); i > 0; --i) {
+ int start = readUnsignedShort(u);
+ int length = readUnsignedShort(u + 2);
+ int index = readUnsignedShort(u + 8);
+ String vsignature = null;
+ if (typeTable != null) {
+ for (int j = 0; j < typeTable.length; j += 3) {
+ if (typeTable[j] == start && typeTable[j + 1] == index) {
+ vsignature = readUTF8(typeTable[j + 2], c);
+ break;
+ }
+ }
+ }
+ mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c),
+ vsignature, labels[start], labels[start + length],
+ index);
+ u += 10;
+ }
+ }
+
+ // visits the local variables type annotations
+ if (tanns != null) {
+ for (int i = 0; i < tanns.length; ++i) {
+ if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) {
+ int v = readAnnotationTarget(context, tanns[i]);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitLocalVariableAnnotation(context.typeRef,
+ context.typePath, context.start,
+ context.end, context.index, readUTF8(v, c),
+ true));
+ }
+ }
+ }
+ if (itanns != null) {
+ for (int i = 0; i < itanns.length; ++i) {
+ if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) {
+ int v = readAnnotationTarget(context, itanns[i]);
+ v = readAnnotationValues(v + 2, c, true,
+ mv.visitLocalVariableAnnotation(context.typeRef,
+ context.typePath, context.start,
+ context.end, context.index, readUTF8(v, c),
+ false));
+ }
+ }
+ }
+
+ // visits the code attributes
+ while (attributes != null) {
+ Attribute attr = attributes.next;
+ attributes.next = null;
+ mv.visitAttribute(attributes);
+ attributes = attr;
+ }
+
+ // visits the max stack and max locals values
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+
+ /**
+ * Parses a type annotation table to find the labels, and to visit the try
+ * catch block annotations.
+ *
+ * @param u
+ * the start offset of a type annotation table.
+ * @param mv
+ * the method visitor to be used to visit the try catch block
+ * annotations.
+ * @param context
+ * information about the class being parsed.
+ * @param visible
+ * if the type annotation table to parse contains runtime visible
+ * annotations.
+ * @return the start offset of each type annotation in the parsed table.
+ */
+ private int[] readTypeAnnotations(final MethodVisitor mv,
+ final Context context, int u, boolean visible) {
+ char[] c = context.buffer;
+ int[] offsets = new int[readUnsignedShort(u)];
+ u += 2;
+ for (int i = 0; i < offsets.length; ++i) {
+ offsets[i] = u;
+ int target = readInt(u);
+ switch (target >>> 24) {
+ case 0x00: // CLASS_TYPE_PARAMETER
+ case 0x01: // METHOD_TYPE_PARAMETER
+ case 0x16: // METHOD_FORMAL_PARAMETER
+ u += 2;
+ break;
+ case 0x13: // FIELD
+ case 0x14: // METHOD_RETURN
+ case 0x15: // METHOD_RECEIVER
+ u += 1;
+ break;
+ case 0x40: // LOCAL_VARIABLE
+ case 0x41: // RESOURCE_VARIABLE
+ for (int j = readUnsignedShort(u + 1); j > 0; --j) {
+ int start = readUnsignedShort(u + 3);
+ int length = readUnsignedShort(u + 5);
+ readLabel(start, context.labels);
+ readLabel(start + length, context.labels);
+ u += 6;
+ }
+ u += 3;
+ break;
+ case 0x47: // CAST
+ case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+ case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+ u += 4;
+ break;
+ // case 0x10: // CLASS_EXTENDS
+ // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+ // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+ // case 0x17: // THROWS
+ // case 0x42: // EXCEPTION_PARAMETER
+ // case 0x43: // INSTANCEOF
+ // case 0x44: // NEW
+ // case 0x45: // CONSTRUCTOR_REFERENCE
+ // case 0x46: // METHOD_REFERENCE
+ default:
+ u += 3;
+ break;
+ }
+ int pathLength = readByte(u);
+ if ((target >>> 24) == 0x42) {
+ TypePath path = pathLength == 0 ? null : new TypePath(b, u);
+ u += 1 + 2 * pathLength;
+ u = readAnnotationValues(u + 2, c, true,
+ mv.visitTryCatchAnnotation(target, path,
+ readUTF8(u, c), visible));
+ } else {
+ u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null);
+ }
+ }
+ return offsets;
+ }
+
+ /**
+ * Parses the header of a type annotation to extract its target_type and
+ * target_path (the result is stored in the given context), and returns the
+ * start offset of the rest of the type_annotation structure (i.e. the
+ * offset to the type_index field, which is followed by
+ * num_element_value_pairs and then the name,value pairs).
+ *
+ * @param context
+ * information about the class being parsed. This is where the
+ * extracted target_type and target_path must be stored.
+ * @param u
+ * the start offset of a type_annotation structure.
+ * @return the start offset of the rest of the type_annotation structure.
+ */
+ private int readAnnotationTarget(final Context context, int u) {
+ int target = readInt(u);
+ switch (target >>> 24) {
+ case 0x00: // CLASS_TYPE_PARAMETER
+ case 0x01: // METHOD_TYPE_PARAMETER
+ case 0x16: // METHOD_FORMAL_PARAMETER
+ target &= 0xFFFF0000;
+ u += 2;
+ break;
+ case 0x13: // FIELD
+ case 0x14: // METHOD_RETURN
+ case 0x15: // METHOD_RECEIVER
+ target &= 0xFF000000;
+ u += 1;
+ break;
+ case 0x40: // LOCAL_VARIABLE
+ case 0x41: { // RESOURCE_VARIABLE
+ target &= 0xFF000000;
+ int n = readUnsignedShort(u + 1);
+ context.start = new Label[n];
+ context.end = new Label[n];
+ context.index = new int[n];
+ u += 3;
+ for (int i = 0; i < n; ++i) {
+ int start = readUnsignedShort(u);
+ int length = readUnsignedShort(u + 2);
+ context.start[i] = readLabel(start, context.labels);
+ context.end[i] = readLabel(start + length, context.labels);
+ context.index[i] = readUnsignedShort(u + 4);
+ u += 6;
+ }
+ break;
+ }
+ case 0x47: // CAST
+ case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT
+ case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT
+ target &= 0xFF0000FF;
+ u += 4;
+ break;
+ // case 0x10: // CLASS_EXTENDS
+ // case 0x11: // CLASS_TYPE_PARAMETER_BOUND
+ // case 0x12: // METHOD_TYPE_PARAMETER_BOUND
+ // case 0x17: // THROWS
+ // case 0x42: // EXCEPTION_PARAMETER
+ // case 0x43: // INSTANCEOF
+ // case 0x44: // NEW
+ // case 0x45: // CONSTRUCTOR_REFERENCE
+ // case 0x46: // METHOD_REFERENCE
+ default:
+ target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000;
+ u += 3;
+ break;
+ }
+ int pathLength = readByte(u);
+ context.typeRef = target;
+ context.typePath = pathLength == 0 ? null : new TypePath(b, u);
+ return u + 1 + 2 * pathLength;
+ }
+
+ /**
+ * Reads parameter annotations and makes the given visitor visit them.
+ *
+ * @param mv
+ * the visitor that must visit the annotations.
+ * @param context
+ * information about the class being parsed.
+ * @param v
+ * start offset in {@link #b b} of the annotations to be read.
+ * @param visible
+ * <tt>true</tt> if the annotations to be read are visible at
+ * runtime.
+ */
+ private void readParameterAnnotations(final MethodVisitor mv,
+ final Context context, int v, final boolean visible) {
+ int i;
+ int n = b[v++] & 0xFF;
+ // workaround for a bug in javac (javac compiler generates a parameter
+ // annotation array whose size is equal to the number of parameters in
+ // the Java source file, while it should generate an array whose size is
+ // equal to the number of parameters in the method descriptor - which
+ // includes the synthetic parameters added by the compiler). This work-
+ // around supposes that the synthetic parameters are the first ones.
+ int synthetics = Type.getArgumentTypes(context.desc).length - n;
+ AnnotationVisitor av;
+ for (i = 0; i < synthetics; ++i) {
+ // virtual annotation to detect synthetic parameters in MethodWriter
+ av = mv.visitParameterAnnotation(i, "Ljava/lang/Synthetic;", false);
+ if (av != null) {
+ av.visitEnd();
+ }
+ }
+ char[] c = context.buffer;
+ for (; i < n + synthetics; ++i) {
+ int j = readUnsignedShort(v);
+ v += 2;
+ for (; j > 0; --j) {
+ av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible);
+ v = readAnnotationValues(v + 2, c, true, av);
+ }
+ }
+ }
+
+ /**
+ * Reads the values of an annotation and makes the given visitor visit them.
+ *
+ * @param v
+ * the start offset in {@link #b b} of the values to be read
+ * (including the unsigned short that gives the number of
+ * values).
+ * @param buf
+ * buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or {@link #readConst
+ * readConst}.
+ * @param named
+ * if the annotation values are named or not.
+ * @param av
+ * the visitor that must visit the values.
+ * @return the end offset of the annotation values.
+ */
+ private int readAnnotationValues(int v, final char[] buf,
+ final boolean named, final AnnotationVisitor av) {
+ int i = readUnsignedShort(v);
+ v += 2;
+ if (named) {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);
+ }
+ } else {
+ for (; i > 0; --i) {
+ v = readAnnotationValue(v, buf, null, av);
+ }
+ }
+ if (av != null) {
+ av.visitEnd();
+ }
+ return v;
+ }
+
+ /**
+ * Reads a value of an annotation and makes the given visitor visit it.
+ *
+ * @param v
+ * the start offset in {@link #b b} of the value to be read
+ * (<i>not including the value name constant pool index</i>).
+ * @param buf
+ * buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or {@link #readConst
+ * readConst}.
+ * @param name
+ * the name of the value to be read.
+ * @param av
+ * the visitor that must visit the value.
+ * @return the end offset of the annotation value.
+ */
+ private int readAnnotationValue(int v, final char[] buf, final String name,
+ final AnnotationVisitor av) {
+ int i;
+ if (av == null) {
+ switch (b[v] & 0xFF) {
+ case 'e': // enum_const_value
+ return v + 5;
+ case '@': // annotation_value
+ return readAnnotationValues(v + 3, buf, true, null);
+ case '[': // array_value
+ return readAnnotationValues(v + 1, buf, false, null);
+ default:
+ return v + 3;
+ }
+ }
+ switch (b[v++] & 0xFF) {
+ case 'I': // pointer to CONSTANT_Integer
+ case 'J': // pointer to CONSTANT_Long
+ case 'F': // pointer to CONSTANT_Float
+ case 'D': // pointer to CONSTANT_Double
+ av.visit(name, readConst(readUnsignedShort(v), buf));
+ v += 2;
+ break;
+ case 'B': // pointer to CONSTANT_Byte
+ av.visit(name, (byte) readInt(items[readUnsignedShort(v)]));
+ v += 2;
+ break;
+ case 'Z': // pointer to CONSTANT_Boolean
+ av.visit(name,
+ readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE
+ : Boolean.TRUE);
+ v += 2;
+ break;
+ case 'S': // pointer to CONSTANT_Short
+ av.visit(name, (short) readInt(items[readUnsignedShort(v)]));
+ v += 2;
+ break;
+ case 'C': // pointer to CONSTANT_Char
+ av.visit(name, (char) readInt(items[readUnsignedShort(v)]));
+ v += 2;
+ break;
+ case 's': // pointer to CONSTANT_Utf8
+ av.visit(name, readUTF8(v, buf));
+ v += 2;
+ break;
+ case 'e': // enum_const_value
+ av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));
+ v += 4;
+ break;
+ case 'c': // class_info
+ av.visit(name, Type.getType(readUTF8(v, buf)));
+ v += 2;
+ break;
+ case '@': // annotation_value
+ v = readAnnotationValues(v + 2, buf, true,
+ av.visitAnnotation(name, readUTF8(v, buf)));
+ break;
+ case '[': // array_value
+ int size = readUnsignedShort(v);
+ v += 2;
+ if (size == 0) {
+ return readAnnotationValues(v - 2, buf, false,
+ av.visitArray(name));
+ }
+ switch (this.b[v++] & 0xFF) {
+ case 'B':
+ byte[] bv = new byte[size];
+ for (i = 0; i < size; i++) {
+ bv[i] = (byte) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, bv);
+ --v;
+ break;
+ case 'Z':
+ boolean[] zv = new boolean[size];
+ for (i = 0; i < size; i++) {
+ zv[i] = readInt(items[readUnsignedShort(v)]) != 0;
+ v += 3;
+ }
+ av.visit(name, zv);
+ --v;
+ break;
+ case 'S':
+ short[] sv = new short[size];
+ for (i = 0; i < size; i++) {
+ sv[i] = (short) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, sv);
+ --v;
+ break;
+ case 'C':
+ char[] cv = new char[size];
+ for (i = 0; i < size; i++) {
+ cv[i] = (char) readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, cv);
+ --v;
+ break;
+ case 'I':
+ int[] iv = new int[size];
+ for (i = 0; i < size; i++) {
+ iv[i] = readInt(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, iv);
+ --v;
+ break;
+ case 'J':
+ long[] lv = new long[size];
+ for (i = 0; i < size; i++) {
+ lv[i] = readLong(items[readUnsignedShort(v)]);
+ v += 3;
+ }
+ av.visit(name, lv);
+ --v;
+ break;
+ case 'F':
+ float[] fv = new float[size];
+ for (i = 0; i < size; i++) {
+ fv[i] = Float
+ .intBitsToFloat(readInt(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, fv);
+ --v;
+ break;
+ case 'D':
+ double[] dv = new double[size];
+ for (i = 0; i < size; i++) {
+ dv[i] = Double
+ .longBitsToDouble(readLong(items[readUnsignedShort(v)]));
+ v += 3;
+ }
+ av.visit(name, dv);
+ --v;
+ break;
+ default:
+ v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));
+ }
+ }
+ return v;
+ }
+
+ /**
+ * Computes the implicit frame of the method currently being parsed (as
+ * defined in the given {@link Context}) and stores it in the given context.
+ *
+ * @param frame
+ * information about the class being parsed.
+ */
+ private void getImplicitFrame(final Context frame) {
+ String desc = frame.desc;
+ Object[] locals = frame.local;
+ int local = 0;
+ if ((frame.access & Opcodes.ACC_STATIC) == 0) {
+ if ("<init>".equals(frame.name)) {
+ locals[local++] = Opcodes.UNINITIALIZED_THIS;
+ } else {
+ locals[local++] = readClass(header + 2, frame.buffer);
+ }
+ }
+ int i = 1;
+ loop: while (true) {
+ int j = i;
+ switch (desc.charAt(i++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ locals[local++] = Opcodes.INTEGER;
+ break;
+ case 'F':
+ locals[local++] = Opcodes.FLOAT;
+ break;
+ case 'J':
+ locals[local++] = Opcodes.LONG;
+ break;
+ case 'D':
+ locals[local++] = Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (desc.charAt(i) == '[') {
+ ++i;
+ }
+ if (desc.charAt(i) == 'L') {
+ ++i;
+ while (desc.charAt(i) != ';') {
+ ++i;
+ }
+ }
+ locals[local++] = desc.substring(j, ++i);
+ break;
+ case 'L':
+ while (desc.charAt(i) != ';') {
+ ++i;
+ }
+ locals[local++] = desc.substring(j + 1, i++);
+ break;
+ default:
+ break loop;
+ }
+ }
+ frame.localCount = local;
+ }
+
+ /**
+ * Reads a stack map frame and stores the result in the given
+ * {@link Context} object.
+ *
+ * @param stackMap
+ * the start offset of a stack map frame in the class file.
+ * @param zip
+ * if the stack map frame at stackMap is compressed or not.
+ * @param unzip
+ * if the stack map frame must be uncompressed.
+ * @param frame
+ * where the parsed stack map frame must be stored.
+ * @return the offset of the first byte following the parsed frame.
+ */
+ private int readFrame(int stackMap, boolean zip, boolean unzip,
+ Context frame) {
+ char[] c = frame.buffer;
+ Label[] labels = frame.labels;
+ int tag;
+ int delta;
+ if (zip) {
+ tag = b[stackMap++] & 0xFF;
+ } else {
+ tag = MethodWriter.FULL_FRAME;
+ frame.offset = -1;
+ }
+ frame.localDiff = 0;
+ if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) {
+ delta = tag;
+ frame.mode = Opcodes.F_SAME;
+ frame.stackCount = 0;
+ } else if (tag < MethodWriter.RESERVED) {
+ delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;
+ stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
+ frame.mode = Opcodes.F_SAME1;
+ frame.stackCount = 1;
+ } else {
+ delta = readUnsignedShort(stackMap);
+ stackMap += 2;
+ if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
+ stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);
+ frame.mode = Opcodes.F_SAME1;
+ frame.stackCount = 1;
+ } else if (tag >= MethodWriter.CHOP_FRAME
+ && tag < MethodWriter.SAME_FRAME_EXTENDED) {
+ frame.mode = Opcodes.F_CHOP;
+ frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag;
+ frame.localCount -= frame.localDiff;
+ frame.stackCount = 0;
+ } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) {
+ frame.mode = Opcodes.F_SAME;
+ frame.stackCount = 0;
+ } else if (tag < MethodWriter.FULL_FRAME) {
+ int local = unzip ? frame.localCount : 0;
+ for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) {
+ stackMap = readFrameType(frame.local, local++, stackMap, c,
+ labels);
+ }
+ frame.mode = Opcodes.F_APPEND;
+ frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED;
+ frame.localCount += frame.localDiff;
+ frame.stackCount = 0;
+ } else { // if (tag == FULL_FRAME) {
+ frame.mode = Opcodes.F_FULL;
+ int n = readUnsignedShort(stackMap);
+ stackMap += 2;
+ frame.localDiff = n;
+ frame.localCount = n;
+ for (int local = 0; n > 0; n--) {
+ stackMap = readFrameType(frame.local, local++, stackMap, c,
+ labels);
+ }
+ n = readUnsignedShort(stackMap);
+ stackMap += 2;
+ frame.stackCount = n;
+ for (int stack = 0; n > 0; n--) {
+ stackMap = readFrameType(frame.stack, stack++, stackMap, c,
+ labels);
+ }
+ }
+ }
+ frame.offset += delta + 1;
+ readLabel(frame.offset, labels);
+ return stackMap;
+ }
+
+ /**
+ * Reads a stack map frame type and stores it at the given index in the
+ * given array.
+ *
+ * @param frame
+ * the array where the parsed type must be stored.
+ * @param index
+ * the index in 'frame' where the parsed type must be stored.
+ * @param v
+ * the start offset of the stack map frame type to read.
+ * @param buf
+ * a buffer to read strings.
+ * @param labels
+ * the labels of the method currently being parsed, indexed by
+ * their offset. If the parsed type is an Uninitialized type, a
+ * new label for the corresponding NEW instruction is stored in
+ * this array if it does not already exist.
+ * @return the offset of the first byte after the parsed type.
+ */
+ private int readFrameType(final Object[] frame, final int index, int v,
+ final char[] buf, final Label[] labels) {
+ int type = b[v++] & 0xFF;
+ switch (type) {
+ case 0:
+ frame[index] = Opcodes.TOP;
+ break;
+ case 1:
+ frame[index] = Opcodes.INTEGER;
+ break;
+ case 2:
+ frame[index] = Opcodes.FLOAT;
+ break;
+ case 3:
+ frame[index] = Opcodes.DOUBLE;
+ break;
+ case 4:
+ frame[index] = Opcodes.LONG;
+ break;
+ case 5:
+ frame[index] = Opcodes.NULL;
+ break;
+ case 6:
+ frame[index] = Opcodes.UNINITIALIZED_THIS;
+ break;
+ case 7: // Object
+ frame[index] = readClass(v, buf);
+ v += 2;
+ break;
+ default: // Uninitialized
+ frame[index] = readLabel(readUnsignedShort(v), labels);
+ v += 2;
+ }
+ return v;
+ }
+
+ /**
+ * Returns the label corresponding to the given offset. The default
+ * implementation of this method creates a label for the given offset if it
+ * has not been already created.
+ *
+ * @param offset
+ * a bytecode offset in a method.
+ * @param labels
+ * the already created labels, indexed by their offset. If a
+ * label already exists for offset this method must not create a
+ * new one. Otherwise it must store the new label in this array.
+ * @return a non null Label, which must be equal to labels[offset].
+ */
+ protected Label readLabel(int offset, Label[] labels) {
+ if (labels[offset] == null) {
+ labels[offset] = new Label();
+ }
+ return labels[offset];
+ }
+
+ /**
+ * Returns the start index of the attribute_info structure of this class.
+ *
+ * @return the start index of the attribute_info structure of this class.
+ */
+ private int getAttributes() {
+ // skips the header
+ int u = header + 8 + readUnsignedShort(header + 6) * 2;
+ // skips fields and methods
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ for (int j = readUnsignedShort(u + 8); j > 0; --j) {
+ u += 6 + readInt(u + 12);
+ }
+ u += 8;
+ }
+ u += 2;
+ for (int i = readUnsignedShort(u); i > 0; --i) {
+ for (int j = readUnsignedShort(u + 8); j > 0; --j) {
+ u += 6 + readInt(u + 12);
+ }
+ u += 8;
+ }
+ // the attribute_info structure starts just after the methods
+ return u + 2;
+ }
+
+ /**
+ * Reads an attribute in {@link #b b}.
+ *
+ * @param attrs
+ * prototypes of the attributes that must be parsed during the
+ * visit of the class. Any attribute whose type is not equal to
+ * the type of one the prototypes is ignored (i.e. an empty
+ * {@link Attribute} instance is returned).
+ * @param type
+ * the type of the attribute.
+ * @param off
+ * index of the first byte of the attribute's content in
+ * {@link #b b}. The 6 attribute header bytes, containing the
+ * type and the length of the attribute, are not taken into
+ * account here (they have already been read).
+ * @param len
+ * the length of the attribute's content.
+ * @param buf
+ * buffer to be used to call {@link #readUTF8 readUTF8},
+ * {@link #readClass(int,char[]) readClass} or {@link #readConst
+ * readConst}.
+ * @param codeOff
+ * index of the first byte of code's attribute content in
+ * {@link #b b}, or -1 if the attribute to be read is not a code
+ * attribute. The 6 attribute header bytes, containing the type
+ * and the length of the attribute, are not taken into account
+ * here.
+ * @param labels
+ * the labels of the method's code, or <tt>null</tt> if the
+ * attribute to be read is not a code attribute.
+ * @return the attribute that has been read, or <tt>null</tt> to skip this
+ * attribute.
+ */
+ private Attribute readAttribute(final Attribute[] attrs, final String type,
+ final int off, final int len, final char[] buf, final int codeOff,
+ final Label[] labels) {
+ for (int i = 0; i < attrs.length; ++i) {
+ if (attrs[i].type.equals(type)) {
+ return attrs[i].read(this, off, len, buf, codeOff, labels);
+ }
+ }
+ return new Attribute(type).read(this, off, len, null, -1, null);
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: low level parsing
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the number of constant pool items in {@link #b b}.
+ *
+ * @return the number of constant pool items in {@link #b b}.
+ */
+ public int getItemCount() {
+ return items.length;
+ }
+
+ /**
+ * Returns the start index of the constant pool item in {@link #b b}, plus
+ * one. <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param item
+ * the index a constant pool item.
+ * @return the start index of the constant pool item in {@link #b b}, plus
+ * one.
+ */
+ public int getItem(final int item) {
+ return items[item];
+ }
+
+ /**
+ * Returns the maximum length of the strings contained in the constant pool
+ * of the class.
+ *
+ * @return the maximum length of the strings contained in the constant pool
+ * of the class.
+ */
+ public int getMaxStringLength() {
+ return maxStringLength;
+ }
+
+ /**
+ * Reads a byte value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index
+ * the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readByte(final int index) {
+ return b[index] & 0xFF;
+ }
+
+ /**
+ * Reads an unsigned short value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index
+ * the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readUnsignedShort(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in {@link #b b}. <i>This method is intended
+ * for {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index
+ * the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public short readShort(final int index) {
+ byte[] b = this.b;
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index
+ * the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public int readInt(final int index) {
+ byte[] b = this.b;
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Reads a signed long value in {@link #b b}. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @param index
+ * the start index of the value to be read in {@link #b b}.
+ * @return the read value.
+ */
+ public long readLong(final int index) {
+ long l1 = readInt(index);
+ long l0 = readInt(index + 4) & 0xFFFFFFFFL;
+ return (l1 << 32) | l0;
+ }
+
+ /**
+ * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method
+ * is intended for {@link Attribute} sub classes, and is normally not needed
+ * by class generators or adapters.</i>
+ *
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of an UTF8 constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 item.
+ */
+ public String readUTF8(int index, final char[] buf) {
+ int item = readUnsignedShort(index);
+ if (index == 0 || item == 0) {
+ return null;
+ }
+ String s = strings[item];
+ if (s != null) {
+ return s;
+ }
+ index = items[item];
+ return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);
+ }
+
+ /**
+ * Reads UTF8 string in {@link #b b}.
+ *
+ * @param index
+ * start offset of the UTF8 string to be read.
+ * @param utfLen
+ * length of the UTF8 string to be read.
+ * @param buf
+ * buffer to be used to read the string. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified UTF8 string.
+ */
+ private String readUTF(int index, final int utfLen, final char[] buf) {
+ int endIndex = index + utfLen;
+ byte[] b = this.b;
+ int strLen = 0;
+ int c;
+ int st = 0;
+ char cc = 0;
+ while (index < endIndex) {
+ c = b[index++];
+ switch (st) {
+ case 0:
+ c = c & 0xFF;
+ if (c < 0x80) { // 0xxxxxxx
+ buf[strLen++] = (char) c;
+ } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
+ cc = (char) (c & 0x1F);
+ st = 1;
+ } else { // 1110 xxxx 10xx xxxx 10xx xxxx
+ cc = (char) (c & 0x0F);
+ st = 2;
+ }
+ break;
+
+ case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
+ buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+ st = 0;
+ break;
+
+ case 2: // byte 2 of 3-byte char
+ cc = (char) ((cc << 6) | (c & 0x3F));
+ st = 1;
+ break;
+ }
+ }
+ return new String(buf, 0, strLen);
+ }
+
+ /**
+ * Reads a class constant pool item in {@link #b b}. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param index
+ * the start index of an unsigned short value in {@link #b b},
+ * whose value is the index of a class constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the String corresponding to the specified class item.
+ */
+ public String readClass(final int index, final char[] buf) {
+ // computes the start index of the CONSTANT_Class item in b
+ // and reads the CONSTANT_Utf8 item designated by
+ // the first two bytes of this CONSTANT_Class item
+ return readUTF8(items[readUnsignedShort(index)], buf);
+ }
+
+ /**
+ * Reads a numeric or string constant pool item in {@link #b b}. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param item
+ * the index of a constant pool item.
+ * @param buf
+ * buffer to be used to read the item. This buffer must be
+ * sufficiently large. It is not automatically resized.
+ * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},
+ * {@link String}, {@link Type} or {@link Handle} corresponding to
+ * the given constant pool item.
+ */
+ public Object readConst(final int item, final char[] buf) {
+ int index = items[item];
+ switch (b[index - 1]) {
+ case ClassWriter.INT:
+ return readInt(index);
+ case ClassWriter.FLOAT:
+ return Float.intBitsToFloat(readInt(index));
+ case ClassWriter.LONG:
+ return readLong(index);
+ case ClassWriter.DOUBLE:
+ return Double.longBitsToDouble(readLong(index));
+ case ClassWriter.CLASS:
+ return Type.getObjectType(readUTF8(index, buf));
+ case ClassWriter.STR:
+ return readUTF8(index, buf);
+ case ClassWriter.MTYPE:
+ return Type.getMethodType(readUTF8(index, buf));
+ default: // case ClassWriter.HANDLE_BASE + [1..9]:
+ int tag = readByte(index);
+ int[] items = this.items;
+ int cpIndex = items[readUnsignedShort(index + 1)];
+ String owner = readClass(cpIndex, buf);
+ cpIndex = items[readUnsignedShort(cpIndex + 2)];
+ String name = readUTF8(cpIndex, buf);
+ String desc = readUTF8(cpIndex + 2, buf);
+ return new Handle(tag, owner, name, desc);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassVisitor.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassVisitor.java
new file mode 100644
index 0000000..e7e1dd6
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassVisitor.java
@@ -0,0 +1,320 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A visitor to visit a Java class. The methods of this class must be called in
+ * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [
+ * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (
+ * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*
+ * <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class ClassVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ protected final int api;
+
+ /**
+ * The class visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected ClassVisitor cv;
+
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ public ClassVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link ClassVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param cv
+ * the class visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public ClassVisitor(final int api, final ClassVisitor cv) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.cv = cv;
+ }
+
+ /**
+ * Visits the header of the class.
+ *
+ * @param version
+ * the class version.
+ * @param access
+ * the class's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the class is deprecated.
+ * @param name
+ * the internal name of the class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param signature
+ * the signature of this class. May be <tt>null</tt> if the class
+ * is not a generic one, and does not extend or implement generic
+ * classes or interfaces.
+ * @param superName
+ * the internal of name of the super class (see
+ * {@link Type#getInternalName() getInternalName}). For
+ * interfaces, the super class is {@link Object}. May be
+ * <tt>null</tt>, but only for the {@link Object} class.
+ * @param interfaces
+ * the internal names of the class's interfaces (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ */
+ public void visit(int version, int access, String name, String signature,
+ String superName, String[] interfaces) {
+ if (cv != null) {
+ cv.visit(version, access, name, signature, superName, interfaces);
+ }
+ }
+
+ /**
+ * Visits the source of the class.
+ *
+ * @param source
+ * the name of the source file from which the class was compiled.
+ * May be <tt>null</tt>.
+ * @param debug
+ * additional debug information to compute the correspondance
+ * between source and compiled elements of the class. May be
+ * <tt>null</tt>.
+ */
+ public void visitSource(String source, String debug) {
+ if (cv != null) {
+ cv.visitSource(source, debug);
+ }
+ }
+
+ /**
+ * Visits the enclosing class of the class. This method must be called only
+ * if the class has an enclosing class.
+ *
+ * @param owner
+ * internal name of the enclosing class of the class.
+ * @param name
+ * the name of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ * @param desc
+ * the descriptor of the method that contains the class, or
+ * <tt>null</tt> if the class is not enclosed in a method of its
+ * enclosing class.
+ */
+ public void visitOuterClass(String owner, String name, String desc) {
+ if (cv != null) {
+ cv.visitOuterClass(owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits an annotation of the class.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (cv != null) {
+ return cv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation on a type in the class signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#CLASS_TYPE_PARAMETER
+ * CLASS_TYPE_PARAMETER},
+ * {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND
+ * CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (cv != null) {
+ return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of the class.
+ *
+ * @param attr
+ * an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (cv != null) {
+ cv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Visits information about an inner class. This inner class is not
+ * necessarily a member of the class being visited.
+ *
+ * @param name
+ * the internal name of an inner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param outerName
+ * the internal name of the class to which the inner class
+ * belongs (see {@link Type#getInternalName() getInternalName}).
+ * May be <tt>null</tt> for not member classes.
+ * @param innerName
+ * the (simple) name of the inner class inside its enclosing
+ * class. May be <tt>null</tt> for anonymous inner classes.
+ * @param access
+ * the access flags of the inner class as originally declared in
+ * the enclosing class.
+ */
+ public void visitInnerClass(String name, String outerName,
+ String innerName, int access) {
+ if (cv != null) {
+ cv.visitInnerClass(name, outerName, innerName, access);
+ }
+ }
+
+ /**
+ * Visits a field of the class.
+ *
+ * @param access
+ * the field's access flags (see {@link Opcodes}). This parameter
+ * also indicates if the field is synthetic and/or deprecated.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt> if the field's
+ * type does not use generic types.
+ * @param value
+ * the field's initial value. This parameter, which may be
+ * <tt>null</tt> if the field does not have an initial value,
+ * must be an {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double} or a {@link String} (for <tt>int</tt>,
+ * <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields
+ * respectively). <i>This parameter is only used for static
+ * fields</i>. Its value is ignored for non static fields, which
+ * must be initialized through bytecode instructions in
+ * constructors or methods.
+ * @return a visitor to visit field annotations and attributes, or
+ * <tt>null</tt> if this class visitor is not interested in visiting
+ * these annotations and attributes.
+ */
+ public FieldVisitor visitField(int access, String name, String desc,
+ String signature, Object value) {
+ if (cv != null) {
+ return cv.visitField(access, name, desc, signature, value);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a method of the class. This method <i>must</i> return a new
+ * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,
+ * i.e., it should not return a previously returned visitor.
+ *
+ * @param access
+ * the method's access flags (see {@link Opcodes}). This
+ * parameter also indicates if the method is synthetic and/or
+ * deprecated.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt> if the method
+ * parameters, return type and exceptions do not use generic
+ * types.
+ * @param exceptions
+ * the internal names of the method's exception classes (see
+ * {@link Type#getInternalName() getInternalName}). May be
+ * <tt>null</tt>.
+ * @return an object to visit the byte code of the method, or <tt>null</tt>
+ * if this class visitor is not interested in visiting the code of
+ * this method.
+ */
+ public MethodVisitor visitMethod(int access, String name, String desc,
+ String signature, String[] exceptions) {
+ if (cv != null) {
+ return cv.visitMethod(access, name, desc, signature, exceptions);
+ }
+ return null;
+ }
+
+ /**
+ * Visits the end of the class. This method, which is the last one to be
+ * called, is used to inform the visitor that all the fields and methods of
+ * the class have been visited.
+ */
+ public void visitEnd() {
+ if (cv != null) {
+ cv.visitEnd();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassWriter.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassWriter.java
new file mode 100644
index 0000000..c8aa340
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/ClassWriter.java
@@ -0,0 +1,1776 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A {@link ClassVisitor} that generates classes in bytecode form. More
+ * precisely this visitor generates a byte array conforming to the Java class
+ * file format. It can be used alone, to generate a Java class "from scratch",
+ * or with one or more {@link ClassReader ClassReader} and adapter class visitor
+ * to generate a modified class from one or more existing Java classes.
+ *
+ * @author Eric Bruneton
+ */
+public class ClassWriter extends ClassVisitor {
+
+ /**
+ * Flag to automatically compute the maximum stack size and the maximum
+ * number of local variables of methods. If this flag is set, then the
+ * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the
+ * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}
+ * method will be ignored, and computed automatically from the signature and
+ * the bytecode of each method.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_MAXS = 1;
+
+ /**
+ * Flag to automatically compute the stack map frames of methods from
+ * scratch. If this flag is set, then the calls to the
+ * {@link MethodVisitor#visitFrame} method are ignored, and the stack map
+ * frames are recomputed from the methods bytecode. The arguments of the
+ * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and
+ * recomputed from the bytecode. In other words, computeFrames implies
+ * computeMaxs.
+ *
+ * @see #ClassWriter(int)
+ */
+ public static final int COMPUTE_FRAMES = 2;
+
+ /**
+ * Pseudo access flag to distinguish between the synthetic attribute and the
+ * synthetic access flag.
+ */
+ static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;
+
+ /**
+ * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.
+ */
+ static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE
+ / Opcodes.ACC_SYNTHETIC;
+
+ /**
+ * The type of instructions without any argument.
+ */
+ static final int NOARG_INSN = 0;
+
+ /**
+ * The type of instructions with an signed byte argument.
+ */
+ static final int SBYTE_INSN = 1;
+
+ /**
+ * The type of instructions with an signed short argument.
+ */
+ static final int SHORT_INSN = 2;
+
+ /**
+ * The type of instructions with a local variable index argument.
+ */
+ static final int VAR_INSN = 3;
+
+ /**
+ * The type of instructions with an implicit local variable index argument.
+ */
+ static final int IMPLVAR_INSN = 4;
+
+ /**
+ * The type of instructions with a type descriptor argument.
+ */
+ static final int TYPE_INSN = 5;
+
+ /**
+ * The type of field and method invocations instructions.
+ */
+ static final int FIELDORMETH_INSN = 6;
+
+ /**
+ * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.
+ */
+ static final int ITFMETH_INSN = 7;
+
+ /**
+ * The type of the INVOKEDYNAMIC instruction.
+ */
+ static final int INDYMETH_INSN = 8;
+
+ /**
+ * The type of instructions with a 2 bytes bytecode offset label.
+ */
+ static final int LABEL_INSN = 9;
+
+ /**
+ * The type of instructions with a 4 bytes bytecode offset label.
+ */
+ static final int LABELW_INSN = 10;
+
+ /**
+ * The type of the LDC instruction.
+ */
+ static final int LDC_INSN = 11;
+
+ /**
+ * The type of the LDC_W and LDC2_W instructions.
+ */
+ static final int LDCW_INSN = 12;
+
+ /**
+ * The type of the IINC instruction.
+ */
+ static final int IINC_INSN = 13;
+
+ /**
+ * The type of the TABLESWITCH instruction.
+ */
+ static final int TABL_INSN = 14;
+
+ /**
+ * The type of the LOOKUPSWITCH instruction.
+ */
+ static final int LOOK_INSN = 15;
+
+ /**
+ * The type of the MULTIANEWARRAY instruction.
+ */
+ static final int MANA_INSN = 16;
+
+ /**
+ * The type of the WIDE instruction.
+ */
+ static final int WIDE_INSN = 17;
+
+ /**
+ * The instruction types of all JVM opcodes.
+ */
+ static final byte[] TYPE;
+
+ /**
+ * The type of CONSTANT_Class constant pool items.
+ */
+ static final int CLASS = 7;
+
+ /**
+ * The type of CONSTANT_Fieldref constant pool items.
+ */
+ static final int FIELD = 9;
+
+ /**
+ * The type of CONSTANT_Methodref constant pool items.
+ */
+ static final int METH = 10;
+
+ /**
+ * The type of CONSTANT_InterfaceMethodref constant pool items.
+ */
+ static final int IMETH = 11;
+
+ /**
+ * The type of CONSTANT_String constant pool items.
+ */
+ static final int STR = 8;
+
+ /**
+ * The type of CONSTANT_Integer constant pool items.
+ */
+ static final int INT = 3;
+
+ /**
+ * The type of CONSTANT_Float constant pool items.
+ */
+ static final int FLOAT = 4;
+
+ /**
+ * The type of CONSTANT_Long constant pool items.
+ */
+ static final int LONG = 5;
+
+ /**
+ * The type of CONSTANT_Double constant pool items.
+ */
+ static final int DOUBLE = 6;
+
+ /**
+ * The type of CONSTANT_NameAndType constant pool items.
+ */
+ static final int NAME_TYPE = 12;
+
+ /**
+ * The type of CONSTANT_Utf8 constant pool items.
+ */
+ static final int UTF8 = 1;
+
+ /**
+ * The type of CONSTANT_MethodType constant pool items.
+ */
+ static final int MTYPE = 16;
+
+ /**
+ * The type of CONSTANT_MethodHandle constant pool items.
+ */
+ static final int HANDLE = 15;
+
+ /**
+ * The type of CONSTANT_InvokeDynamic constant pool items.
+ */
+ static final int INDY = 18;
+
+ /**
+ * The base value for all CONSTANT_MethodHandle constant pool items.
+ * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9
+ * different items.
+ */
+ static final int HANDLE_BASE = 20;
+
+ /**
+ * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_NORMAL = 30;
+
+ /**
+ * Uninitialized type Item stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table.
+ */
+ static final int TYPE_UNINIT = 31;
+
+ /**
+ * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},
+ * instead of the constant pool, in order to avoid clashes with normal
+ * constant pool items in the ClassWriter constant pool's hash table.
+ */
+ static final int TYPE_MERGED = 32;
+
+ /**
+ * The type of BootstrapMethods items. These items are stored in a special
+ * class attribute named BootstrapMethods and not in the constant pool.
+ */
+ static final int BSM = 33;
+
+ /**
+ * The class reader from which this class writer was constructed, if any.
+ */
+ ClassReader cr;
+
+ /**
+ * Minor and major version numbers of the class to be generated.
+ */
+ int version;
+
+ /**
+ * Index of the next item to be added in the constant pool.
+ */
+ int index;
+
+ /**
+ * The constant pool of this class.
+ */
+ final ByteVector pool;
+
+ /**
+ * The constant pool's hash table data.
+ */
+ Item[] items;
+
+ /**
+ * The threshold of the constant pool's hash table.
+ */
+ int threshold;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key2;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key3;
+
+ /**
+ * A reusable key used to look for items in the {@link #items} hash table.
+ */
+ final Item key4;
+
+ /**
+ * A type table used to temporarily store internal names that will not
+ * necessarily be stored in the constant pool. This type table is used by
+ * the control flow and data flow analysis algorithm used to compute stack
+ * map frames from scratch. This array associates to each index <tt>i</tt>
+ * the Item whose index is <tt>i</tt>. All Item objects stored in this array
+ * are also stored in the {@link #items} hash table. These two arrays allow
+ * to retrieve an Item from its index or, conversely, to get the index of an
+ * Item from its value. Each Item stores an internal name in its
+ * {@link Item#strVal1} field.
+ */
+ Item[] typeTable;
+
+ /**
+ * Number of elements in the {@link #typeTable} array.
+ */
+ private short typeCount;
+
+ /**
+ * The access flags of this class.
+ */
+ private int access;
+
+ /**
+ * The constant pool item that contains the internal name of this class.
+ */
+ private int name;
+
+ /**
+ * The internal name of this class.
+ */
+ String thisName;
+
+ /**
+ * The constant pool item that contains the signature of this class.
+ */
+ private int signature;
+
+ /**
+ * The constant pool item that contains the internal name of the super class
+ * of this class.
+ */
+ private int superName;
+
+ /**
+ * Number of interfaces implemented or extended by this class or interface.
+ */
+ private int interfaceCount;
+
+ /**
+ * The interfaces implemented or extended by this class or interface. More
+ * precisely, this array contains the indexes of the constant pool items
+ * that contain the internal names of these interfaces.
+ */
+ private int[] interfaces;
+
+ /**
+ * The index of the constant pool item that contains the name of the source
+ * file from which this class was compiled.
+ */
+ private int sourceFile;
+
+ /**
+ * The SourceDebug attribute of this class.
+ */
+ private ByteVector sourceDebug;
+
+ /**
+ * The constant pool item that contains the name of the enclosing class of
+ * this class.
+ */
+ private int enclosingMethodOwner;
+
+ /**
+ * The constant pool item that contains the name and descriptor of the
+ * enclosing method of this class.
+ */
+ private int enclosingMethod;
+
+ /**
+ * The runtime visible annotations of this class.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this class.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The runtime visible type annotations of this class.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this class.
+ */
+ private AnnotationWriter itanns;
+
+ /**
+ * The non standard attributes of this class.
+ */
+ private Attribute attrs;
+
+ /**
+ * The number of entries in the InnerClasses attribute.
+ */
+ private int innerClassesCount;
+
+ /**
+ * The InnerClasses attribute.
+ */
+ private ByteVector innerClasses;
+
+ /**
+ * The number of entries in the BootstrapMethods attribute.
+ */
+ int bootstrapMethodsCount;
+
+ /**
+ * The BootstrapMethods attribute.
+ */
+ ByteVector bootstrapMethods;
+
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#fv} field. This field stores the first element of this
+ * list.
+ */
+ FieldWriter firstField;
+
+ /**
+ * The fields of this class. These fields are stored in a linked list of
+ * {@link FieldWriter} objects, linked to each other by their
+ * {@link FieldWriter#fv} field. This field stores the last element of this
+ * list.
+ */
+ FieldWriter lastField;
+
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#mv} field. This field stores the first element of
+ * this list.
+ */
+ MethodWriter firstMethod;
+
+ /**
+ * The methods of this class. These methods are stored in a linked list of
+ * {@link MethodWriter} objects, linked to each other by their
+ * {@link MethodWriter#mv} field. This field stores the last element of this
+ * list.
+ */
+ MethodWriter lastMethod;
+
+ /**
+ * <tt>true</tt> if the maximum stack size and number of local variables
+ * must be automatically computed.
+ */
+ private boolean computeMaxs;
+
+ /**
+ * <tt>true</tt> if the stack map frames must be recomputed from scratch.
+ */
+ private boolean computeFrames;
+
+ /**
+ * <tt>true</tt> if the stack map tables of this class are invalid. The
+ * {@link MethodWriter#resizeInstructions} method cannot transform existing
+ * stack map tables, and so produces potentially invalid classes when it is
+ * executed. In this case the class is reread and rewritten with the
+ * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize
+ * stack map tables when this option is used).
+ */
+ boolean invalidFrames;
+
+ // ------------------------------------------------------------------------
+ // Static initializer
+ // ------------------------------------------------------------------------
+
+ /**
+ * Computes the instruction types of JVM opcodes.
+ */
+ static {
+ int i;
+ byte[] b = new byte[220];
+ String s = "AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD"
+ + "DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
+ + "AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA"
+ + "AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = (byte) (s.charAt(i) - 'A');
+ }
+ TYPE = b;
+
+ // code to generate the above string
+ //
+ // // SBYTE_INSN instructions
+ // b[Constants.NEWARRAY] = SBYTE_INSN;
+ // b[Constants.BIPUSH] = SBYTE_INSN;
+ //
+ // // SHORT_INSN instructions
+ // b[Constants.SIPUSH] = SHORT_INSN;
+ //
+ // // (IMPL)VAR_INSN instructions
+ // b[Constants.RET] = VAR_INSN;
+ // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {
+ // b[i] = VAR_INSN;
+ // }
+ // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3
+ // b[i] = IMPLVAR_INSN;
+ // }
+ //
+ // // TYPE_INSN instructions
+ // b[Constants.NEW] = TYPE_INSN;
+ // b[Constants.ANEWARRAY] = TYPE_INSN;
+ // b[Constants.CHECKCAST] = TYPE_INSN;
+ // b[Constants.INSTANCEOF] = TYPE_INSN;
+ //
+ // // (Set)FIELDORMETH_INSN instructions
+ // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {
+ // b[i] = FIELDORMETH_INSN;
+ // }
+ // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;
+ // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;
+ //
+ // // LABEL(W)_INSN instructions
+ // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ // b[Constants.IFNULL] = LABEL_INSN;
+ // b[Constants.IFNONNULL] = LABEL_INSN;
+ // b[200] = LABELW_INSN; // GOTO_W
+ // b[201] = LABELW_INSN; // JSR_W
+ // // temporary opcodes used internally by ASM - see Label and
+ // MethodWriter
+ // for (i = 202; i < 220; ++i) {
+ // b[i] = LABEL_INSN;
+ // }
+ //
+ // // LDC(_W) instructions
+ // b[Constants.LDC] = LDC_INSN;
+ // b[19] = LDCW_INSN; // LDC_W
+ // b[20] = LDCW_INSN; // LDC2_W
+ //
+ // // special instructions
+ // b[Constants.IINC] = IINC_INSN;
+ // b[Constants.TABLESWITCH] = TABL_INSN;
+ // b[Constants.LOOKUPSWITCH] = LOOK_INSN;
+ // b[Constants.MULTIANEWARRAY] = MANA_INSN;
+ // b[196] = WIDE_INSN; // WIDE
+ //
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('A' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link ClassWriter} object.
+ *
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final int flags) {
+ super(Opcodes.ASM5);
+ index = 1;
+ pool = new ByteVector();
+ items = new Item[256];
+ threshold = (int) (0.75d * items.length);
+ key = new Item();
+ key2 = new Item();
+ key3 = new Item();
+ key4 = new Item();
+ this.computeMaxs = (flags & COMPUTE_MAXS) != 0;
+ this.computeFrames = (flags & COMPUTE_FRAMES) != 0;
+ }
+
+ /**
+ * Constructs a new {@link ClassWriter} object and enables optimizations for
+ * "mostly add" bytecode transformations. These optimizations are the
+ * following:
+ *
+ * <ul>
+ * <li>The constant pool from the original class is copied as is in the new
+ * class, which saves time. New constant pool entries will be added at the
+ * end if necessary, but unused constant pool entries <i>won't be
+ * removed</i>.</li>
+ * <li>Methods that are not transformed are copied as is in the new class,
+ * directly from the original class bytecode (i.e. without emitting visit
+ * events for all the method instructions), which saves a <i>lot</i> of
+ * time. Untransformed methods are detected by the fact that the
+ * {@link ClassReader} receives {@link MethodVisitor} objects that come from
+ * a {@link ClassWriter} (and not from any other {@link ClassVisitor}
+ * instance).</li>
+ * </ul>
+ *
+ * @param classReader
+ * the {@link ClassReader} used to read the original class. It
+ * will be used to copy the entire constant pool from the
+ * original class and also to copy other fragments of original
+ * bytecode where applicable.
+ * @param flags
+ * option flags that can be used to modify the default behavior
+ * of this class. <i>These option flags do not affect methods
+ * that are copied as is in the new class. This means that the
+ * maximum stack size nor the stack frames will be computed for
+ * these methods</i>. See {@link #COMPUTE_MAXS},
+ * {@link #COMPUTE_FRAMES}.
+ */
+ public ClassWriter(final ClassReader classReader, final int flags) {
+ this(flags);
+ classReader.copyPool(this);
+ this.cr = classReader;
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the ClassVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public final void visit(final int version, final int access,
+ final String name, final String signature, final String superName,
+ final String[] interfaces) {
+ this.version = version;
+ this.access = access;
+ this.name = newClass(name);
+ thisName = name;
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = newUTF8(signature);
+ }
+ this.superName = superName == null ? 0 : newClass(superName);
+ if (interfaces != null && interfaces.length > 0) {
+ interfaceCount = interfaces.length;
+ this.interfaces = new int[interfaceCount];
+ for (int i = 0; i < interfaceCount; ++i) {
+ this.interfaces[i] = newClass(interfaces[i]);
+ }
+ }
+ }
+
+ @Override
+ public final void visitSource(final String file, final String debug) {
+ if (file != null) {
+ sourceFile = newUTF8(file);
+ }
+ if (debug != null) {
+ sourceDebug = new ByteVector().encodeUTF8(debug, 0,
+ Integer.MAX_VALUE);
+ }
+ }
+
+ @Override
+ public final void visitOuterClass(final String owner, final String name,
+ final String desc) {
+ enclosingMethodOwner = newClass(owner);
+ if (name != null && desc != null) {
+ enclosingMethod = newNameType(name, desc);
+ }
+ }
+
+ @Override
+ public final AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public final AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public final void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ @Override
+ public final void visitInnerClass(final String name,
+ final String outerName, final String innerName, final int access) {
+ if (innerClasses == null) {
+ innerClasses = new ByteVector();
+ }
+ // Sec. 4.7.6 of the JVMS states "Every CONSTANT_Class_info entry in the
+ // constant_pool table which represents a class or interface C that is
+ // not a package member must have exactly one corresponding entry in the
+ // classes array". To avoid duplicates we keep track in the intVal field
+ // of the Item of each CONSTANT_Class_info entry C whether an inner
+ // class entry has already been added for C (this field is unused for
+ // class entries, and changing its value does not change the hashcode
+ // and equality tests). If so we store the index of this inner class
+ // entry (plus one) in intVal. This hack allows duplicate detection in
+ // O(1) time.
+ Item nameItem = newClassItem(name);
+ if (nameItem.intVal == 0) {
+ ++innerClassesCount;
+ innerClasses.putShort(nameItem.index);
+ innerClasses.putShort(outerName == null ? 0 : newClass(outerName));
+ innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));
+ innerClasses.putShort(access);
+ nameItem.intVal = innerClassesCount;
+ } else {
+ // Compare the inner classes entry nameItem.intVal - 1 with the
+ // arguments of this method and throw an exception if there is a
+ // difference?
+ }
+ }
+
+ @Override
+ public final FieldVisitor visitField(final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ return new FieldWriter(this, access, name, desc, signature, value);
+ }
+
+ @Override
+ public final MethodVisitor visitMethod(final int access, final String name,
+ final String desc, final String signature, final String[] exceptions) {
+ return new MethodWriter(this, access, name, desc, signature,
+ exceptions, computeMaxs, computeFrames);
+ }
+
+ @Override
+ public final void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Other public methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the bytecode of the class that was build with this class writer.
+ *
+ * @return the bytecode of the class that was build with this class writer.
+ */
+ public byte[] toByteArray() {
+ if (index > 0xFFFF) {
+ throw new RuntimeException("Class file too large!");
+ }
+ // computes the real size of the bytecode of this class
+ int size = 24 + 2 * interfaceCount;
+ int nbFields = 0;
+ FieldWriter fb = firstField;
+ while (fb != null) {
+ ++nbFields;
+ size += fb.getSize();
+ fb = (FieldWriter) fb.fv;
+ }
+ int nbMethods = 0;
+ MethodWriter mb = firstMethod;
+ while (mb != null) {
+ ++nbMethods;
+ size += mb.getSize();
+ mb = (MethodWriter) mb.mv;
+ }
+ int attributeCount = 0;
+ if (bootstrapMethods != null) {
+ // we put it as first attribute in order to improve a bit
+ // ClassReader.copyBootstrapMethods
+ ++attributeCount;
+ size += 8 + bootstrapMethods.length;
+ newUTF8("BootstrapMethods");
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("Signature");
+ }
+ if (sourceFile != 0) {
+ ++attributeCount;
+ size += 8;
+ newUTF8("SourceFile");
+ }
+ if (sourceDebug != null) {
+ ++attributeCount;
+ size += sourceDebug.length + 6;
+ newUTF8("SourceDebugExtension");
+ }
+ if (enclosingMethodOwner != 0) {
+ ++attributeCount;
+ size += 10;
+ newUTF8("EnclosingMethod");
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Deprecated");
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ size += 6;
+ newUTF8("Synthetic");
+ }
+ }
+ if (innerClasses != null) {
+ ++attributeCount;
+ size += 8 + innerClasses.length;
+ newUTF8("InnerClasses");
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ size += 8 + anns.getSize();
+ newUTF8("RuntimeVisibleAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ size += 8 + ianns.getSize();
+ newUTF8("RuntimeInvisibleAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ size += 8 + tanns.getSize();
+ newUTF8("RuntimeVisibleTypeAnnotations");
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ size += 8 + itanns.getSize();
+ newUTF8("RuntimeInvisibleTypeAnnotations");
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ size += attrs.getSize(this, null, 0, -1, -1);
+ }
+ size += pool.length;
+ // allocates a byte vector of this size, in order to avoid unnecessary
+ // arraycopy operations in the ByteVector.enlarge() method
+ ByteVector out = new ByteVector(size);
+ out.putInt(0xCAFEBABE).putInt(version);
+ out.putShort(index).putByteArray(pool.data, 0, pool.length);
+ int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);
+ out.putShort(access & ~mask).putShort(name).putShort(superName);
+ out.putShort(interfaceCount);
+ for (int i = 0; i < interfaceCount; ++i) {
+ out.putShort(interfaces[i]);
+ }
+ out.putShort(nbFields);
+ fb = firstField;
+ while (fb != null) {
+ fb.put(out);
+ fb = (FieldWriter) fb.fv;
+ }
+ out.putShort(nbMethods);
+ mb = firstMethod;
+ while (mb != null) {
+ mb.put(out);
+ mb = (MethodWriter) mb.mv;
+ }
+ out.putShort(attributeCount);
+ if (bootstrapMethods != null) {
+ out.putShort(newUTF8("BootstrapMethods"));
+ out.putInt(bootstrapMethods.length + 2).putShort(
+ bootstrapMethodsCount);
+ out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(newUTF8("Signature")).putInt(2).putShort(signature);
+ }
+ if (sourceFile != 0) {
+ out.putShort(newUTF8("SourceFile")).putInt(2).putShort(sourceFile);
+ }
+ if (sourceDebug != null) {
+ int len = sourceDebug.length;
+ out.putShort(newUTF8("SourceDebugExtension")).putInt(len);
+ out.putByteArray(sourceDebug.data, 0, len);
+ }
+ if (enclosingMethodOwner != 0) {
+ out.putShort(newUTF8("EnclosingMethod")).putInt(4);
+ out.putShort(enclosingMethodOwner).putShort(enclosingMethod);
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(newUTF8("Deprecated")).putInt(0);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((version & 0xFFFF) < Opcodes.V1_5
+ || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(newUTF8("Synthetic")).putInt(0);
+ }
+ }
+ if (innerClasses != null) {
+ out.putShort(newUTF8("InnerClasses"));
+ out.putInt(innerClasses.length + 2).putShort(innerClassesCount);
+ out.putByteArray(innerClasses.data, 0, innerClasses.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(this, null, 0, -1, -1, out);
+ }
+ if (invalidFrames) {
+ anns = null;
+ ianns = null;
+ attrs = null;
+ innerClassesCount = 0;
+ innerClasses = null;
+ bootstrapMethodsCount = 0;
+ bootstrapMethods = null;
+ firstField = null;
+ lastField = null;
+ firstMethod = null;
+ lastMethod = null;
+ computeMaxs = false;
+ computeFrames = true;
+ invalidFrames = false;
+ new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);
+ return toByteArray();
+ }
+ return out.data;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: constant pool management
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double}, a {@link String} or a
+ * {@link Type}.
+ * @return a new or already existing constant item with the given value.
+ */
+ Item newConstItem(final Object cst) {
+ if (cst instanceof Integer) {
+ int val = ((Integer) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Byte) {
+ int val = ((Byte) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Character) {
+ int val = ((Character) cst).charValue();
+ return newInteger(val);
+ } else if (cst instanceof Short) {
+ int val = ((Short) cst).intValue();
+ return newInteger(val);
+ } else if (cst instanceof Boolean) {
+ int val = ((Boolean) cst).booleanValue() ? 1 : 0;
+ return newInteger(val);
+ } else if (cst instanceof Float) {
+ float val = ((Float) cst).floatValue();
+ return newFloat(val);
+ } else if (cst instanceof Long) {
+ long val = ((Long) cst).longValue();
+ return newLong(val);
+ } else if (cst instanceof Double) {
+ double val = ((Double) cst).doubleValue();
+ return newDouble(val);
+ } else if (cst instanceof String) {
+ return newString((String) cst);
+ } else if (cst instanceof Type) {
+ Type t = (Type) cst;
+ int s = t.getSort();
+ if (s == Type.OBJECT) {
+ return newClassItem(t.getInternalName());
+ } else if (s == Type.METHOD) {
+ return newMethodTypeItem(t.getDescriptor());
+ } else { // s == primitive type or array
+ return newClassItem(t.getDescriptor());
+ }
+ } else if (cst instanceof Handle) {
+ Handle h = (Handle) cst;
+ return newHandleItem(h.tag, h.owner, h.name, h.desc);
+ } else {
+ throw new IllegalArgumentException("value " + cst);
+ }
+ }
+
+ /**
+ * Adds a number or string constant to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param cst
+ * the value of the constant to be added to the constant pool.
+ * This parameter must be an {@link Integer}, a {@link Float}, a
+ * {@link Long}, a {@link Double} or a {@link String}.
+ * @return the index of a new or already existing constant item with the
+ * given value.
+ */
+ public int newConst(final Object cst) {
+ return newConstItem(cst).index;
+ }
+
+ /**
+ * Adds an UTF8 string to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param value
+ * the String value.
+ * @return the index of a new or already existing UTF8 item.
+ */
+ public int newUTF8(final String value) {
+ key.set(UTF8, value, null, null);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(UTF8).putUTF8(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value
+ * the internal name of the class.
+ * @return a new or already existing class reference item.
+ */
+ Item newClassItem(final String value) {
+ key2.set(CLASS, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(CLASS, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a class reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param value
+ * the internal name of the class.
+ * @return the index of a new or already existing class reference item.
+ */
+ public int newClass(final String value) {
+ return newClassItem(value).index;
+ }
+
+ /**
+ * Adds a method type reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
+ * @return a new or already existing method type reference item.
+ */
+ Item newMethodTypeItem(final String methodDesc) {
+ key2.set(MTYPE, methodDesc, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(MTYPE, newUTF8(methodDesc));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a method type reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param methodDesc
+ * method descriptor of the method type.
+ * @return the index of a new or already existing method type reference
+ * item.
+ */
+ public int newMethodType(final String methodDesc) {
+ return newMethodTypeItem(methodDesc).index;
+ }
+
+ /**
+ * Adds a handle to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
+ * @return a new or an already existing method type reference item.
+ */
+ Item newHandleItem(final int tag, final String owner, final String name,
+ final String desc) {
+ key4.set(HANDLE_BASE + tag, owner, name, desc);
+ Item result = get(key4);
+ if (result == null) {
+ if (tag <= Opcodes.H_PUTSTATIC) {
+ put112(HANDLE, tag, newField(owner, name, desc));
+ } else {
+ put112(HANDLE,
+ tag,
+ newMethod(owner, name, desc,
+ tag == Opcodes.H_INVOKEINTERFACE));
+ }
+ result = new Item(index++, key4);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a handle to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item. <i>This method is
+ * intended for {@link Attribute} sub classes, and is normally not needed by
+ * class generators or adapters.</i>
+ *
+ * @param tag
+ * the kind of this handle. Must be {@link Opcodes#H_GETFIELD},
+ * {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},
+ * {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the field or method owner class.
+ * @param name
+ * the name of the field or method.
+ * @param desc
+ * the descriptor of the field or method.
+ * @return the index of a new or already existing method type reference
+ * item.
+ */
+ public int newHandle(final int tag, final String owner, final String name,
+ final String desc) {
+ return newHandleItem(tag, owner, name, desc).index;
+ }
+
+ /**
+ * Adds an invokedynamic reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
+ * @return a new or an already existing invokedynamic type reference item.
+ */
+ Item newInvokeDynamicItem(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
+ // cache for performance
+ ByteVector bootstrapMethods = this.bootstrapMethods;
+ if (bootstrapMethods == null) {
+ bootstrapMethods = this.bootstrapMethods = new ByteVector();
+ }
+
+ int position = bootstrapMethods.length; // record current position
+
+ int hashCode = bsm.hashCode();
+ bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,
+ bsm.desc));
+
+ int argsLength = bsmArgs.length;
+ bootstrapMethods.putShort(argsLength);
+
+ for (int i = 0; i < argsLength; i++) {
+ Object bsmArg = bsmArgs[i];
+ hashCode ^= bsmArg.hashCode();
+ bootstrapMethods.putShort(newConst(bsmArg));
+ }
+
+ byte[] data = bootstrapMethods.data;
+ int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)
+ hashCode &= 0x7FFFFFFF;
+ Item result = items[hashCode % items.length];
+ loop: while (result != null) {
+ if (result.type != BSM || result.hashCode != hashCode) {
+ result = result.next;
+ continue;
+ }
+
+ // because the data encode the size of the argument
+ // we don't need to test if these size are equals
+ int resultPosition = result.intVal;
+ for (int p = 0; p < length; p++) {
+ if (data[position + p] != data[resultPosition + p]) {
+ result = result.next;
+ continue loop;
+ }
+ }
+ break;
+ }
+
+ int bootstrapMethodIndex;
+ if (result != null) {
+ bootstrapMethodIndex = result.index;
+ bootstrapMethods.length = position; // revert to old position
+ } else {
+ bootstrapMethodIndex = bootstrapMethodsCount++;
+ result = new Item(bootstrapMethodIndex);
+ result.set(position, hashCode);
+ put(result);
+ }
+
+ // now, create the InvokeDynamic constant
+ key3.set(name, desc, bootstrapMethodIndex);
+ result = get(key3);
+ if (result == null) {
+ put122(INDY, bootstrapMethodIndex, newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds an invokedynamic reference to the constant pool of the class being
+ * build. Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param name
+ * name of the invoked method.
+ * @param desc
+ * descriptor of the invoke method.
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments.
+ *
+ * @return the index of a new or already existing invokedynamic reference
+ * item.
+ */
+ public int newInvokeDynamic(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
+ return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
+ * @return a new or already existing field reference item.
+ */
+ Item newFieldItem(final String owner, final String name, final String desc) {
+ key3.set(FIELD, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(FIELD, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a field reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner
+ * the internal name of the field's owner class.
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor.
+ * @return the index of a new or already existing field reference item.
+ */
+ public int newField(final String owner, final String name, final String desc) {
+ return newFieldItem(owner, name, desc).index;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return a new or already existing method reference item.
+ */
+ Item newMethodItem(final String owner, final String name,
+ final String desc, final boolean itf) {
+ int type = itf ? IMETH : METH;
+ key3.set(type, owner, name, desc);
+ Item result = get(key3);
+ if (result == null) {
+ put122(type, newClass(owner), newNameType(name, desc));
+ result = new Item(index++, key3);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a method reference to the constant pool of the class being build.
+ * Does nothing if the constant pool already contains a similar item.
+ * <i>This method is intended for {@link Attribute} sub classes, and is
+ * normally not needed by class generators or adapters.</i>
+ *
+ * @param owner
+ * the internal name of the method's owner class.
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor.
+ * @param itf
+ * <tt>true</tt> if <tt>owner</tt> is an interface.
+ * @return the index of a new or already existing method reference item.
+ */
+ public int newMethod(final String owner, final String name,
+ final String desc, final boolean itf) {
+ return newMethodItem(owner, name, desc, itf).index;
+ }
+
+ /**
+ * Adds an integer to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param value
+ * the int value.
+ * @return a new or already existing int item.
+ */
+ Item newInteger(final int value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(INT).putInt(value);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a float to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value
+ * the float value.
+ * @return a new or already existing float item.
+ */
+ Item newFloat(final float value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(FLOAT).putInt(key.intVal);
+ result = new Item(index++, key);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a long to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value
+ * the long value.
+ * @return a new or already existing long item.
+ */
+ Item newLong(final long value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(LONG).putLong(value);
+ result = new Item(index, key);
+ index += 2;
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a double to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value
+ * the double value.
+ * @return a new or already existing double item.
+ */
+ Item newDouble(final double value) {
+ key.set(value);
+ Item result = get(key);
+ if (result == null) {
+ pool.putByte(DOUBLE).putLong(key.longVal);
+ result = new Item(index, key);
+ index += 2;
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a string to the constant pool of the class being build. Does nothing
+ * if the constant pool already contains a similar item.
+ *
+ * @param value
+ * the String value.
+ * @return a new or already existing string item.
+ */
+ private Item newString(final String value) {
+ key2.set(STR, value, null, null);
+ Item result = get(key2);
+ if (result == null) {
+ pool.put12(STR, newUTF8(value));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds a name and type to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item. <i>This
+ * method is intended for {@link Attribute} sub classes, and is normally not
+ * needed by class generators or adapters.</i>
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
+ * @return the index of a new or already existing name and type item.
+ */
+ public int newNameType(final String name, final String desc) {
+ return newNameTypeItem(name, desc).index;
+ }
+
+ /**
+ * Adds a name and type to the constant pool of the class being build. Does
+ * nothing if the constant pool already contains a similar item.
+ *
+ * @param name
+ * a name.
+ * @param desc
+ * a type descriptor.
+ * @return a new or already existing name and type item.
+ */
+ Item newNameTypeItem(final String name, final String desc) {
+ key2.set(NAME_TYPE, name, desc, null);
+ Item result = get(key2);
+ if (result == null) {
+ put122(NAME_TYPE, newUTF8(name), newUTF8(desc));
+ result = new Item(index++, key2);
+ put(result);
+ }
+ return result;
+ }
+
+ /**
+ * Adds the given internal name to {@link #typeTable} and returns its index.
+ * Does nothing if the type table already contains this internal name.
+ *
+ * @param type
+ * the internal name to be added to the type table.
+ * @return the index of this internal name in the type table.
+ */
+ int addType(final String type) {
+ key.set(TYPE_NORMAL, type, null, null);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given "uninitialized" type to {@link #typeTable} and returns its
+ * index. This method is used for UNINITIALIZED types, made of an internal
+ * name and a bytecode offset.
+ *
+ * @param type
+ * the internal name to be added to the type table.
+ * @param offset
+ * the bytecode offset of the NEW instruction that created this
+ * UNINITIALIZED type value.
+ * @return the index of this internal name in the type table.
+ */
+ int addUninitializedType(final String type, final int offset) {
+ key.type = TYPE_UNINIT;
+ key.intVal = offset;
+ key.strVal1 = type;
+ key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);
+ Item result = get(key);
+ if (result == null) {
+ result = addType(key);
+ }
+ return result.index;
+ }
+
+ /**
+ * Adds the given Item to {@link #typeTable}.
+ *
+ * @param item
+ * the value to be added to the type table.
+ * @return the added Item, which a new Item instance with the same value as
+ * the given Item.
+ */
+ private Item addType(final Item item) {
+ ++typeCount;
+ Item result = new Item(typeCount, key);
+ put(result);
+ if (typeTable == null) {
+ typeTable = new Item[16];
+ }
+ if (typeCount == typeTable.length) {
+ Item[] newTable = new Item[2 * typeTable.length];
+ System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);
+ typeTable = newTable;
+ }
+ typeTable[typeCount] = result;
+ return result;
+ }
+
+ /**
+ * Returns the index of the common super type of the two given types. This
+ * method calls {@link #getCommonSuperClass} and caches the result in the
+ * {@link #items} hash table to speedup future calls with the same
+ * parameters.
+ *
+ * @param type1
+ * index of an internal name in {@link #typeTable}.
+ * @param type2
+ * index of an internal name in {@link #typeTable}.
+ * @return the index of the common super type of the two given types.
+ */
+ int getMergedType(final int type1, final int type2) {
+ key2.type = TYPE_MERGED;
+ key2.longVal = type1 | (((long) type2) << 32);
+ key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);
+ Item result = get(key2);
+ if (result == null) {
+ String t = typeTable[type1].strVal1;
+ String u = typeTable[type2].strVal1;
+ key2.intVal = addType(getCommonSuperClass(t, u));
+ result = new Item((short) 0, key2);
+ put(result);
+ }
+ return result.intVal;
+ }
+
+ /**
+ * Returns the common super type of the two given types. The default
+ * implementation of this method <i>loads</i> the two given classes and uses
+ * the java.lang.Class methods to find the common super class. It can be
+ * overridden to compute this common super type in other ways, in particular
+ * without actually loading any class, or to take into account the class
+ * that is currently being generated by this ClassWriter, which can of
+ * course not be loaded since it is under construction.
+ *
+ * @param type1
+ * the internal name of a class.
+ * @param type2
+ * the internal name of another class.
+ * @return the internal name of the common super class of the two given
+ * classes.
+ */
+ protected String getCommonSuperClass(final String type1, final String type2) {
+ Class<?> c, d;
+ ClassLoader classLoader = getClass().getClassLoader();
+ try {
+ c = Class.forName(type1.replace('/', '.'), false, classLoader);
+ d = Class.forName(type2.replace('/', '.'), false, classLoader);
+ } catch (Exception e) {
+ throw new RuntimeException(e.toString());
+ }
+ if (c.isAssignableFrom(d)) {
+ return type1;
+ }
+ if (d.isAssignableFrom(c)) {
+ return type2;
+ }
+ if (c.isInterface() || d.isInterface()) {
+ return "java/lang/Object";
+ } else {
+ do {
+ c = c.getSuperclass();
+ } while (!c.isAssignableFrom(d));
+ return c.getName().replace('.', '/');
+ }
+ }
+
+ /**
+ * Returns the constant pool's hash table item which is equal to the given
+ * item.
+ *
+ * @param key
+ * a constant pool item.
+ * @return the constant pool's hash table item which is equal to the given
+ * item, or <tt>null</tt> if there is no such item.
+ */
+ private Item get(final Item key) {
+ Item i = items[key.hashCode % items.length];
+ while (i != null && (i.type != key.type || !key.isEqualTo(i))) {
+ i = i.next;
+ }
+ return i;
+ }
+
+ /**
+ * Puts the given item in the constant pool's hash table. The hash table
+ * <i>must</i> not already contains this item.
+ *
+ * @param i
+ * the item to be added to the constant pool's hash table.
+ */
+ private void put(final Item i) {
+ if (index + typeCount > threshold) {
+ int ll = items.length;
+ int nl = ll * 2 + 1;
+ Item[] newItems = new Item[nl];
+ for (int l = ll - 1; l >= 0; --l) {
+ Item j = items[l];
+ while (j != null) {
+ int index = j.hashCode % newItems.length;
+ Item k = j.next;
+ j.next = newItems[index];
+ newItems[index] = j;
+ j = k;
+ }
+ }
+ items = newItems;
+ threshold = (int) (nl * 0.75);
+ }
+ int index = i.hashCode % items.length;
+ i.next = items[index];
+ items[index] = i;
+ }
+
+ /**
+ * Puts one byte and two shorts into the constant pool.
+ *
+ * @param b
+ * a byte.
+ * @param s1
+ * a short.
+ * @param s2
+ * another short.
+ */
+ private void put122(final int b, final int s1, final int s2) {
+ pool.put12(b, s1).putShort(s2);
+ }
+
+ /**
+ * Puts two bytes and one short into the constant pool.
+ *
+ * @param b1
+ * a byte.
+ * @param b2
+ * another byte.
+ * @param s
+ * a short.
+ */
+ private void put112(final int b1, final int b2, final int s) {
+ pool.put11(b1, b2).putShort(s);
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Context.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Context.java
new file mode 100644
index 0000000..382fd69
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Context.java
@@ -0,0 +1,145 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.powermock.objectweb.asm;
+
+/**
+ * Information about a class being parsed in a {@link ClassReader}.
+ *
+ * @author Eric Bruneton
+ */
+class Context {
+
+ /**
+ * Prototypes of the attributes that must be parsed for this class.
+ */
+ Attribute[] attrs;
+
+ /**
+ * The {@link ClassReader} option flags for the parsing of this class.
+ */
+ int flags;
+
+ /**
+ * The buffer used to read strings.
+ */
+ char[] buffer;
+
+ /**
+ * The start index of each bootstrap method.
+ */
+ int[] bootstrapMethods;
+
+ /**
+ * The access flags of the method currently being parsed.
+ */
+ int access;
+
+ /**
+ * The name of the method currently being parsed.
+ */
+ String name;
+
+ /**
+ * The descriptor of the method currently being parsed.
+ */
+ String desc;
+
+ /**
+ * The label objects, indexed by bytecode offset, of the method currently
+ * being parsed (only bytecode offsets for which a label is needed have a
+ * non null associated Label object).
+ */
+ Label[] labels;
+
+ /**
+ * The target of the type annotation currently being parsed.
+ */
+ int typeRef;
+
+ /**
+ * The path of the type annotation currently being parsed.
+ */
+ TypePath typePath;
+
+ /**
+ * The offset of the latest stack map frame that has been parsed.
+ */
+ int offset;
+
+ /**
+ * The labels corresponding to the start of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] start;
+
+ /**
+ * The labels corresponding to the end of the local variable ranges in the
+ * local variable type annotation currently being parsed.
+ */
+ Label[] end;
+
+ /**
+ * The local variable indices for each local variable range in the local
+ * variable type annotation currently being parsed.
+ */
+ int[] index;
+
+ /**
+ * The encoding of the latest stack map frame that has been parsed.
+ */
+ int mode;
+
+ /**
+ * The number of locals in the latest stack map frame that has been parsed.
+ */
+ int localCount;
+
+ /**
+ * The number locals in the latest stack map frame that has been parsed,
+ * minus the number of locals in the previous frame.
+ */
+ int localDiff;
+
+ /**
+ * The local values of the latest stack map frame that has been parsed.
+ */
+ Object[] local;
+
+ /**
+ * The stack size of the latest stack map frame that has been parsed.
+ */
+ int stackCount;
+
+ /**
+ * The stack values of the latest stack map frame that has been parsed.
+ */
+ Object[] stack;
+}
\ No newline at end of file
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Edge.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Edge.java
new file mode 100644
index 0000000..ee745af
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Edge.java
@@ -0,0 +1,75 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * An edge in the control flow graph of a method body. See {@link Label Label}.
+ *
+ * @author Eric Bruneton
+ */
+class Edge {
+
+ /**
+ * Denotes a normal control flow graph edge.
+ */
+ static final int NORMAL = 0;
+
+ /**
+ * Denotes a control flow graph edge corresponding to an exception handler.
+ * More precisely any {@link Edge} whose {@link #info} is strictly positive
+ * corresponds to an exception handler. The actual value of {@link #info} is
+ * the index, in the {@link ClassWriter} type table, of the exception that
+ * is catched.
+ */
+ static final int EXCEPTION = 0x7FFFFFFF;
+
+ /**
+ * Information about this control flow graph edge. If
+ * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)
+ * stack size in the basic block from which this edge originates. This size
+ * is equal to the stack size at the "jump" instruction to which this edge
+ * corresponds, relatively to the stack size at the beginning of the
+ * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,
+ * this field is the kind of this control flow graph edge (i.e. NORMAL or
+ * EXCEPTION).
+ */
+ int info;
+
+ /**
+ * The successor block of the basic block from which this edge originates.
+ */
+ Label successor;
+
+ /**
+ * The next edge in the list of successors of the originating basic block.
+ * See {@link Label#successors successors}.
+ */
+ Edge next;
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldVisitor.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldVisitor.java
new file mode 100644
index 0000000..d10bb20
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldVisitor.java
@@ -0,0 +1,150 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A visitor to visit a Java field. The methods of this class must be called in
+ * the following order: ( <tt>visitAnnotation</tt> |
+ * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class FieldVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ protected final int api;
+
+ /**
+ * The field visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected FieldVisitor fv;
+
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ public FieldVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link FieldVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param fv
+ * the field visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public FieldVisitor(final int api, final FieldVisitor fv) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.fv = fv;
+ }
+
+ /**
+ * Visits an annotation of the field.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (fv != null) {
+ return fv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation on the type of the field.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#FIELD FIELD}. See
+ * {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (fv != null) {
+ return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of the field.
+ *
+ * @param attr
+ * an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (fv != null) {
+ fv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Visits the end of the field. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the field have been visited.
+ */
+ public void visitEnd() {
+ if (fv != null) {
+ fv.visitEnd();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldWriter.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldWriter.java
new file mode 100644
index 0000000..28af785
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/FieldWriter.java
@@ -0,0 +1,329 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * An {@link FieldVisitor} that generates Java fields in bytecode form.
+ *
+ * @author Eric Bruneton
+ */
+final class FieldWriter extends FieldVisitor {
+
+ /**
+ * The class writer to which this field must be added.
+ */
+ private final ClassWriter cw;
+
+ /**
+ * Access flags of this field.
+ */
+ private final int access;
+
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * field.
+ */
+ private final int desc;
+
+ /**
+ * The index of the constant pool item that contains the signature of this
+ * field.
+ */
+ private int signature;
+
+ /**
+ * The index of the constant pool item that contains the constant value of
+ * this field.
+ */
+ private int value;
+
+ /**
+ * The runtime visible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The runtime visible type annotations of this field. May be <tt>null</tt>.
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this field. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
+ * The non standard attributes of this field. May be <tt>null</tt>.
+ */
+ private Attribute attrs;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link FieldWriter}.
+ *
+ * @param cw
+ * the class writer to which this field must be added.
+ * @param access
+ * the field's access flags (see {@link Opcodes}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type}).
+ * @param signature
+ * the field's signature. May be <tt>null</tt>.
+ * @param value
+ * the field's constant value. May be <tt>null</tt>.
+ */
+ FieldWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature, final Object value) {
+ super(Opcodes.ASM5);
+ if (cw.firstField == null) {
+ cw.firstField = this;
+ } else {
+ cw.lastField.fv = this;
+ }
+ cw.lastField = this;
+ this.cw = cw;
+ this.access = access;
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ if (ClassReader.SIGNATURES && signature != null) {
+ this.signature = cw.newUTF8(signature);
+ }
+ if (value != null) {
+ this.value = cw.newConstItem(value).index;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the FieldVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ attr.next = attrs;
+ attrs = attr;
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of this field.
+ *
+ * @return the size of this field.
+ */
+ int getSize() {
+ int size = 8;
+ if (value != 0) {
+ cw.newUTF8("ConstantValue");
+ size += 8;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ cw.newUTF8("Signature");
+ size += 8;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the content of this field into the given byte vector.
+ *
+ * @param out
+ * where the content of this field must be put.
+ */
+ void put(final ByteVector out) {
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
+ out.putShort(access & ~mask).putShort(name).putShort(desc);
+ int attributeCount = 0;
+ if (value != 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (value != 0) {
+ out.putShort(cw.newUTF8("ConstantValue"));
+ out.putInt(2).putShort(value);
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != 0) {
+ out.putShort(cw.newUTF8("Signature"));
+ out.putInt(2).putShort(signature);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Frame.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Frame.java
new file mode 100644
index 0000000..7402fac
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Frame.java
@@ -0,0 +1,1462 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * Information about the input and output stack map frames of a basic block.
+ *
+ * @author Eric Bruneton
+ */
+final class Frame {
+
+ /*
+ * Frames are computed in a two steps process: during the visit of each
+ * instruction, the state of the frame at the end of current basic block is
+ * updated by simulating the action of the instruction on the previous state
+ * of this so called "output frame". In visitMaxs, a fix point algorithm is
+ * used to compute the "input frame" of each basic block, i.e. the stack map
+ * frame at the beginning of the basic block, starting from the input frame
+ * of the first basic block (which is computed from the method descriptor),
+ * and by using the previously computed output frames to compute the input
+ * state of the other blocks.
+ *
+ * All output and input frames are stored as arrays of integers. Reference
+ * and array types are represented by an index into a type table (which is
+ * not the same as the constant pool of the class, in order to avoid adding
+ * unnecessary constants in the pool - not all computed frames will end up
+ * being stored in the stack map table). This allows very fast type
+ * comparisons.
+ *
+ * Output stack map frames are computed relatively to the input frame of the
+ * basic block, which is not yet known when output frames are computed. It
+ * is therefore necessary to be able to represent abstract types such as
+ * "the type at position x in the input frame locals" or "the type at
+ * position x from the top of the input frame stack" or even "the type at
+ * position x in the input frame, with y more (or less) array dimensions".
+ * This explains the rather complicated type format used in output frames.
+ *
+ * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a
+ * signed number of array dimensions (from -8 to 7). KIND is either BASE,
+ * LOCAL or STACK. BASE is used for types that are not relative to the input
+ * frame. LOCAL is used for types that are relative to the input local
+ * variable types. STACK is used for types that are relative to the input
+ * stack types. VALUE depends on KIND. For LOCAL types, it is an index in
+ * the input local variable types. For STACK types, it is a position
+ * relatively to the top of input frame stack. For BASE types, it is either
+ * one of the constants defined below, or for OBJECT and UNINITIALIZED
+ * types, a tag and an index in the type table.
+ *
+ * Output frames can contain types of any kind and with a positive or
+ * negative dimension (and even unassigned types, represented by 0 - which
+ * does not correspond to any valid type value). Input frames can only
+ * contain BASE types of positive or null dimension. In all cases the type
+ * table contains only internal type names (array type descriptors are
+ * forbidden - dimensions must be represented through the DIM field).
+ *
+ * The LONG and DOUBLE types are always represented by using two slots (LONG
+ * + TOP or DOUBLE + TOP), for local variable types as well as in the
+ * operand stack. This is necessary to be able to simulate DUPx_y
+ * instructions, whose effect would be dependent on the actual type values
+ * if types were always represented by a single slot in the stack (and this
+ * is not possible, since actual type values are not always known - cf LOCAL
+ * and STACK type kinds).
+ */
+
+ /**
+ * Mask to get the dimension of a frame type. This dimension is a signed
+ * integer between -8 and 7.
+ */
+ static final int DIM = 0xF0000000;
+
+ /**
+ * Constant to be added to a type to get a type with one more dimension.
+ */
+ static final int ARRAY_OF = 0x10000000;
+
+ /**
+ * Constant to be added to a type to get a type with one less dimension.
+ */
+ static final int ELEMENT_OF = 0xF0000000;
+
+ /**
+ * Mask to get the kind of a frame type.
+ *
+ * @see #BASE
+ * @see #LOCAL
+ * @see #STACK
+ */
+ static final int KIND = 0xF000000;
+
+ /**
+ * Flag used for LOCAL and STACK types. Indicates that if this type happens
+ * to be a long or double type (during the computations of input frames),
+ * then it must be set to TOP because the second word of this value has been
+ * reused to store other data in the basic block. Hence the first word no
+ * longer stores a valid long or double value.
+ */
+ static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;
+
+ /**
+ * Mask to get the value of a frame type.
+ */
+ static final int VALUE = 0x7FFFFF;
+
+ /**
+ * Mask to get the kind of base types.
+ */
+ static final int BASE_KIND = 0xFF00000;
+
+ /**
+ * Mask to get the value of base types.
+ */
+ static final int BASE_VALUE = 0xFFFFF;
+
+ /**
+ * Kind of the types that are not relative to an input stack map frame.
+ */
+ static final int BASE = 0x1000000;
+
+ /**
+ * Base kind of the base reference types. The BASE_VALUE of such types is an
+ * index into the type table.
+ */
+ static final int OBJECT = BASE | 0x700000;
+
+ /**
+ * Base kind of the uninitialized base types. The BASE_VALUE of such types
+ * in an index into the type table (the Item at that index contains both an
+ * instruction offset and an internal class name).
+ */
+ static final int UNINITIALIZED = BASE | 0x800000;
+
+ /**
+ * Kind of the types that are relative to the local variable types of an
+ * input stack map frame. The value of such types is a local variable index.
+ */
+ private static final int LOCAL = 0x2000000;
+
+ /**
+ * Kind of the the types that are relative to the stack of an input stack
+ * map frame. The value of such types is a position relatively to the top of
+ * this stack.
+ */
+ private static final int STACK = 0x3000000;
+
+ /**
+ * The TOP type. This is a BASE type.
+ */
+ static final int TOP = BASE | 0;
+
+ /**
+ * The BOOLEAN type. This is a BASE type mainly used for array types.
+ */
+ static final int BOOLEAN = BASE | 9;
+
+ /**
+ * The BYTE type. This is a BASE type mainly used for array types.
+ */
+ static final int BYTE = BASE | 10;
+
+ /**
+ * The CHAR type. This is a BASE type mainly used for array types.
+ */
+ static final int CHAR = BASE | 11;
+
+ /**
+ * The SHORT type. This is a BASE type mainly used for array types.
+ */
+ static final int SHORT = BASE | 12;
+
+ /**
+ * The INTEGER type. This is a BASE type.
+ */
+ static final int INTEGER = BASE | 1;
+
+ /**
+ * The FLOAT type. This is a BASE type.
+ */
+ static final int FLOAT = BASE | 2;
+
+ /**
+ * The DOUBLE type. This is a BASE type.
+ */
+ static final int DOUBLE = BASE | 3;
+
+ /**
+ * The LONG type. This is a BASE type.
+ */
+ static final int LONG = BASE | 4;
+
+ /**
+ * The NULL type. This is a BASE type.
+ */
+ static final int NULL = BASE | 5;
+
+ /**
+ * The UNINITIALIZED_THIS type. This is a BASE type.
+ */
+ static final int UNINITIALIZED_THIS = BASE | 6;
+
+ /**
+ * The stack size variation corresponding to each JVM instruction. This
+ * stack variation is equal to the size of the values produced by an
+ * instruction, minus the size of the values consumed by this instruction.
+ */
+ static final int[] SIZE;
+
+ /**
+ * Computes the stack size variation corresponding to each JVM instruction.
+ */
+ static {
+ int i;
+ int[] b = new int[202];
+ String s = "EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD"
+ + "CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD"
+ + "CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED"
+ + "DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE";
+ for (i = 0; i < b.length; ++i) {
+ b[i] = s.charAt(i) - 'E';
+ }
+ SIZE = b;
+
+ // code to generate the above string
+ //
+ // int NA = 0; // not applicable (unused opcode or variable size opcode)
+ //
+ // b = new int[] {
+ // 0, //NOP, // visitInsn
+ // 1, //ACONST_NULL, // -
+ // 1, //ICONST_M1, // -
+ // 1, //ICONST_0, // -
+ // 1, //ICONST_1, // -
+ // 1, //ICONST_2, // -
+ // 1, //ICONST_3, // -
+ // 1, //ICONST_4, // -
+ // 1, //ICONST_5, // -
+ // 2, //LCONST_0, // -
+ // 2, //LCONST_1, // -
+ // 1, //FCONST_0, // -
+ // 1, //FCONST_1, // -
+ // 1, //FCONST_2, // -
+ // 2, //DCONST_0, // -
+ // 2, //DCONST_1, // -
+ // 1, //BIPUSH, // visitIntInsn
+ // 1, //SIPUSH, // -
+ // 1, //LDC, // visitLdcInsn
+ // NA, //LDC_W, // -
+ // NA, //LDC2_W, // -
+ // 1, //ILOAD, // visitVarInsn
+ // 2, //LLOAD, // -
+ // 1, //FLOAD, // -
+ // 2, //DLOAD, // -
+ // 1, //ALOAD, // -
+ // NA, //ILOAD_0, // -
+ // NA, //ILOAD_1, // -
+ // NA, //ILOAD_2, // -
+ // NA, //ILOAD_3, // -
+ // NA, //LLOAD_0, // -
+ // NA, //LLOAD_1, // -
+ // NA, //LLOAD_2, // -
+ // NA, //LLOAD_3, // -
+ // NA, //FLOAD_0, // -
+ // NA, //FLOAD_1, // -
+ // NA, //FLOAD_2, // -
+ // NA, //FLOAD_3, // -
+ // NA, //DLOAD_0, // -
+ // NA, //DLOAD_1, // -
+ // NA, //DLOAD_2, // -
+ // NA, //DLOAD_3, // -
+ // NA, //ALOAD_0, // -
+ // NA, //ALOAD_1, // -
+ // NA, //ALOAD_2, // -
+ // NA, //ALOAD_3, // -
+ // -1, //IALOAD, // visitInsn
+ // 0, //LALOAD, // -
+ // -1, //FALOAD, // -
+ // 0, //DALOAD, // -
+ // -1, //AALOAD, // -
+ // -1, //BALOAD, // -
+ // -1, //CALOAD, // -
+ // -1, //SALOAD, // -
+ // -1, //ISTORE, // visitVarInsn
+ // -2, //LSTORE, // -
+ // -1, //FSTORE, // -
+ // -2, //DSTORE, // -
+ // -1, //ASTORE, // -
+ // NA, //ISTORE_0, // -
+ // NA, //ISTORE_1, // -
+ // NA, //ISTORE_2, // -
+ // NA, //ISTORE_3, // -
+ // NA, //LSTORE_0, // -
+ // NA, //LSTORE_1, // -
+ // NA, //LSTORE_2, // -
+ // NA, //LSTORE_3, // -
+ // NA, //FSTORE_0, // -
+ // NA, //FSTORE_1, // -
+ // NA, //FSTORE_2, // -
+ // NA, //FSTORE_3, // -
+ // NA, //DSTORE_0, // -
+ // NA, //DSTORE_1, // -
+ // NA, //DSTORE_2, // -
+ // NA, //DSTORE_3, // -
+ // NA, //ASTORE_0, // -
+ // NA, //ASTORE_1, // -
+ // NA, //ASTORE_2, // -
+ // NA, //ASTORE_3, // -
+ // -3, //IASTORE, // visitInsn
+ // -4, //LASTORE, // -
+ // -3, //FASTORE, // -
+ // -4, //DASTORE, // -
+ // -3, //AASTORE, // -
+ // -3, //BASTORE, // -
+ // -3, //CASTORE, // -
+ // -3, //SASTORE, // -
+ // -1, //POP, // -
+ // -2, //POP2, // -
+ // 1, //DUP, // -
+ // 1, //DUP_X1, // -
+ // 1, //DUP_X2, // -
+ // 2, //DUP2, // -
+ // 2, //DUP2_X1, // -
+ // 2, //DUP2_X2, // -
+ // 0, //SWAP, // -
+ // -1, //IADD, // -
+ // -2, //LADD, // -
+ // -1, //FADD, // -
+ // -2, //DADD, // -
+ // -1, //ISUB, // -
+ // -2, //LSUB, // -
+ // -1, //FSUB, // -
+ // -2, //DSUB, // -
+ // -1, //IMUL, // -
+ // -2, //LMUL, // -
+ // -1, //FMUL, // -
+ // -2, //DMUL, // -
+ // -1, //IDIV, // -
+ // -2, //LDIV, // -
+ // -1, //FDIV, // -
+ // -2, //DDIV, // -
+ // -1, //IREM, // -
+ // -2, //LREM, // -
+ // -1, //FREM, // -
+ // -2, //DREM, // -
+ // 0, //INEG, // -
+ // 0, //LNEG, // -
+ // 0, //FNEG, // -
+ // 0, //DNEG, // -
+ // -1, //ISHL, // -
+ // -1, //LSHL, // -
+ // -1, //ISHR, // -
+ // -1, //LSHR, // -
+ // -1, //IUSHR, // -
+ // -1, //LUSHR, // -
+ // -1, //IAND, // -
+ // -2, //LAND, // -
+ // -1, //IOR, // -
+ // -2, //LOR, // -
+ // -1, //IXOR, // -
+ // -2, //LXOR, // -
+ // 0, //IINC, // visitIincInsn
+ // 1, //I2L, // visitInsn
+ // 0, //I2F, // -
+ // 1, //I2D, // -
+ // -1, //L2I, // -
+ // -1, //L2F, // -
+ // 0, //L2D, // -
+ // 0, //F2I, // -
+ // 1, //F2L, // -
+ // 1, //F2D, // -
+ // -1, //D2I, // -
+ // 0, //D2L, // -
+ // -1, //D2F, // -
+ // 0, //I2B, // -
+ // 0, //I2C, // -
+ // 0, //I2S, // -
+ // -3, //LCMP, // -
+ // -1, //FCMPL, // -
+ // -1, //FCMPG, // -
+ // -3, //DCMPL, // -
+ // -3, //DCMPG, // -
+ // -1, //IFEQ, // visitJumpInsn
+ // -1, //IFNE, // -
+ // -1, //IFLT, // -
+ // -1, //IFGE, // -
+ // -1, //IFGT, // -
+ // -1, //IFLE, // -
+ // -2, //IF_ICMPEQ, // -
+ // -2, //IF_ICMPNE, // -
+ // -2, //IF_ICMPLT, // -
+ // -2, //IF_ICMPGE, // -
+ // -2, //IF_ICMPGT, // -
+ // -2, //IF_ICMPLE, // -
+ // -2, //IF_ACMPEQ, // -
+ // -2, //IF_ACMPNE, // -
+ // 0, //GOTO, // -
+ // 1, //JSR, // -
+ // 0, //RET, // visitVarInsn
+ // -1, //TABLESWITCH, // visiTableSwitchInsn
+ // -1, //LOOKUPSWITCH, // visitLookupSwitch
+ // -1, //IRETURN, // visitInsn
+ // -2, //LRETURN, // -
+ // -1, //FRETURN, // -
+ // -2, //DRETURN, // -
+ // -1, //ARETURN, // -
+ // 0, //RETURN, // -
+ // NA, //GETSTATIC, // visitFieldInsn
+ // NA, //PUTSTATIC, // -
+ // NA, //GETFIELD, // -
+ // NA, //PUTFIELD, // -
+ // NA, //INVOKEVIRTUAL, // visitMethodInsn
+ // NA, //INVOKESPECIAL, // -
+ // NA, //INVOKESTATIC, // -
+ // NA, //INVOKEINTERFACE, // -
+ // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn
+ // 1, //NEW, // visitTypeInsn
+ // 0, //NEWARRAY, // visitIntInsn
+ // 0, //ANEWARRAY, // visitTypeInsn
+ // 0, //ARRAYLENGTH, // visitInsn
+ // NA, //ATHROW, // -
+ // 0, //CHECKCAST, // visitTypeInsn
+ // 0, //INSTANCEOF, // -
+ // -1, //MONITORENTER, // visitInsn
+ // -1, //MONITOREXIT, // -
+ // NA, //WIDE, // NOT VISITED
+ // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn
+ // -1, //IFNULL, // visitJumpInsn
+ // -1, //IFNONNULL, // -
+ // NA, //GOTO_W, // -
+ // NA, //JSR_W, // -
+ // };
+ // for (i = 0; i < b.length; ++i) {
+ // System.err.print((char)('E' + b[i]));
+ // }
+ // System.err.println();
+ }
+
+ /**
+ * The label (i.e. basic block) to which these input and output stack map
+ * frames correspond.
+ */
+ Label owner;
+
+ /**
+ * The input stack map frame locals.
+ */
+ int[] inputLocals;
+
+ /**
+ * The input stack map frame stack.
+ */
+ int[] inputStack;
+
+ /**
+ * The output stack map frame locals.
+ */
+ private int[] outputLocals;
+
+ /**
+ * The output stack map frame stack.
+ */
+ private int[] outputStack;
+
+ /**
+ * Relative size of the output stack. The exact semantics of this field
+ * depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the size of
+ * the output stack relatively to the top of the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * actual number of types in {@link #outputStack}.
+ */
+ private int outputStackTop;
+
+ /**
+ * Number of types that are initialized in the basic block.
+ *
+ * @see #initializations
+ */
+ private int initializationCount;
+
+ /**
+ * The types that are initialized in the basic block. A constructor
+ * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace
+ * <i>every occurence</i> of this type in the local variables and in the
+ * operand stack. This cannot be done during the first phase of the
+ * algorithm since, during this phase, the local variables and the operand
+ * stack are not completely computed. It is therefore necessary to store the
+ * types on which constructors are invoked in the basic block, in order to
+ * do this replacement during the second phase of the algorithm, where the
+ * frames are fully computed. Note that this array can contain types that
+ * are relative to input locals or to the input stack (see below for the
+ * description of the algorithm).
+ */
+ private int[] initializations;
+
+ /**
+ * Returns the output frame local variable type at the given index.
+ *
+ * @param local
+ * the index of the local that must be returned.
+ * @return the output frame local variable type at the given index.
+ */
+ private int get(final int local) {
+ if (outputLocals == null || local >= outputLocals.length) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ return LOCAL | local;
+ } else {
+ int type = outputLocals[local];
+ if (type == 0) {
+ // this local has never been assigned in this basic block,
+ // so it is still equal to its value in the input frame
+ type = outputLocals[local] = LOCAL | local;
+ }
+ return type;
+ }
+ }
+
+ /**
+ * Sets the output frame local variable type at the given index.
+ *
+ * @param local
+ * the index of the local that must be set.
+ * @param type
+ * the value of the local that must be set.
+ */
+ private void set(final int local, final int type) {
+ // creates and/or resizes the output local variables array if necessary
+ if (outputLocals == null) {
+ outputLocals = new int[10];
+ }
+ int n = outputLocals.length;
+ if (local >= n) {
+ int[] t = new int[Math.max(local + 1, 2 * n)];
+ System.arraycopy(outputLocals, 0, t, 0, n);
+ outputLocals = t;
+ }
+ // sets the local variable
+ outputLocals[local] = type;
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param type
+ * the type that must be pushed.
+ */
+ private void push(final int type) {
+ // creates and/or resizes the output stack array if necessary
+ if (outputStack == null) {
+ outputStack = new int[10];
+ }
+ int n = outputStack.length;
+ if (outputStackTop >= n) {
+ int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];
+ System.arraycopy(outputStack, 0, t, 0, n);
+ outputStack = t;
+ }
+ // pushes the type on the output stack
+ outputStack[outputStackTop++] = type;
+ // updates the maximun height reached by the output stack, if needed
+ int top = owner.inputStackTop + outputStackTop;
+ if (top > owner.outputStackMax) {
+ owner.outputStackMax = top;
+ }
+ }
+
+ /**
+ * Pushes a new type onto the output frame stack.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * the descriptor of the type to be pushed. Can also be a method
+ * descriptor (in this case this method pushes its return type
+ * onto the output frame stack).
+ */
+ private void push(final ClassWriter cw, final String desc) {
+ int type = type(cw, desc);
+ if (type != 0) {
+ push(type);
+ if (type == LONG || type == DOUBLE) {
+ push(TOP);
+ }
+ }
+ }
+
+ /**
+ * Returns the int encoding of the given type.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param desc
+ * a type descriptor.
+ * @return the int encoding of the given type.
+ */
+ private static int type(final ClassWriter cw, final String desc) {
+ String t;
+ int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;
+ switch (desc.charAt(index)) {
+ case 'V':
+ return 0;
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ return INTEGER;
+ case 'F':
+ return FLOAT;
+ case 'J':
+ return LONG;
+ case 'D':
+ return DOUBLE;
+ case 'L':
+ // stores the internal name, not the descriptor!
+ t = desc.substring(index + 1, desc.length() - 1);
+ return OBJECT | cw.addType(t);
+ // case '[':
+ default:
+ // extracts the dimensions and the element type
+ int data;
+ int dims = index + 1;
+ while (desc.charAt(dims) == '[') {
+ ++dims;
+ }
+ switch (desc.charAt(dims)) {
+ case 'Z':
+ data = BOOLEAN;
+ break;
+ case 'C':
+ data = CHAR;
+ break;
+ case 'B':
+ data = BYTE;
+ break;
+ case 'S':
+ data = SHORT;
+ break;
+ case 'I':
+ data = INTEGER;
+ break;
+ case 'F':
+ data = FLOAT;
+ break;
+ case 'J':
+ data = LONG;
+ break;
+ case 'D':
+ data = DOUBLE;
+ break;
+ // case 'L':
+ default:
+ // stores the internal name, not the descriptor
+ t = desc.substring(dims + 1, desc.length() - 1);
+ data = OBJECT | cw.addType(t);
+ }
+ return (dims - index) << 28 | data;
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack and returns its value.
+ *
+ * @return the type that has been popped from the output frame stack.
+ */
+ private int pop() {
+ if (outputStackTop > 0) {
+ return outputStack[--outputStackTop];
+ } else {
+ // if the output frame stack is empty, pops from the input stack
+ return STACK | -(--owner.inputStackTop);
+ }
+ }
+
+ /**
+ * Pops the given number of types from the output frame stack.
+ *
+ * @param elements
+ * the number of types that must be popped.
+ */
+ private void pop(final int elements) {
+ if (outputStackTop >= elements) {
+ outputStackTop -= elements;
+ } else {
+ // if the number of elements to be popped is greater than the number
+ // of elements in the output stack, clear it, and pops the remaining
+ // elements from the input stack.
+ owner.inputStackTop -= elements - outputStackTop;
+ outputStackTop = 0;
+ }
+ }
+
+ /**
+ * Pops a type from the output frame stack.
+ *
+ * @param desc
+ * the descriptor of the type to be popped. Can also be a method
+ * descriptor (in this case this method pops the types
+ * corresponding to the method arguments).
+ */
+ private void pop(final String desc) {
+ char c = desc.charAt(0);
+ if (c == '(') {
+ pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);
+ } else if (c == 'J' || c == 'D') {
+ pop(2);
+ } else {
+ pop(1);
+ }
+ }
+
+ /**
+ * Adds a new type to the list of types on which a constructor is invoked in
+ * the basic block.
+ *
+ * @param var
+ * a type on a which a constructor is invoked.
+ */
+ private void init(final int var) {
+ // creates and/or resizes the initializations array if necessary
+ if (initializations == null) {
+ initializations = new int[2];
+ }
+ int n = initializations.length;
+ if (initializationCount >= n) {
+ int[] t = new int[Math.max(initializationCount + 1, 2 * n)];
+ System.arraycopy(initializations, 0, t, 0, n);
+ initializations = t;
+ }
+ // stores the type to be initialized
+ initializations[initializationCount++] = var;
+ }
+
+ /**
+ * Replaces the given type with the appropriate type if it is one of the
+ * types on which a constructor is invoked in the basic block.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * a type
+ * @return t or, if t is one of the types on which a constructor is invoked
+ * in the basic block, the type corresponding to this constructor.
+ */
+ private int init(final ClassWriter cw, final int t) {
+ int s;
+ if (t == UNINITIALIZED_THIS) {
+ s = OBJECT | cw.addType(cw.thisName);
+ } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {
+ String type = cw.typeTable[t & BASE_VALUE].strVal1;
+ s = OBJECT | cw.addType(type);
+ } else {
+ return t;
+ }
+ for (int j = 0; j < initializationCount; ++j) {
+ int u = initializations[j];
+ int dim = u & DIM;
+ int kind = u & KIND;
+ if (kind == LOCAL) {
+ u = dim + inputLocals[u & VALUE];
+ } else if (kind == STACK) {
+ u = dim + inputStack[inputStack.length - (u & VALUE)];
+ }
+ if (t == u) {
+ return s;
+ }
+ }
+ return t;
+ }
+
+ /**
+ * Initializes the input frame of the first basic block from the method
+ * descriptor.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param access
+ * the access flags of the method to which this label belongs.
+ * @param args
+ * the formal parameter types of this method.
+ * @param maxLocals
+ * the maximum number of local variables of this method.
+ */
+ void initInputFrame(final ClassWriter cw, final int access,
+ final Type[] args, final int maxLocals) {
+ inputLocals = new int[maxLocals];
+ inputStack = new int[0];
+ int i = 0;
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {
+ inputLocals[i++] = OBJECT | cw.addType(cw.thisName);
+ } else {
+ inputLocals[i++] = UNINITIALIZED_THIS;
+ }
+ }
+ for (int j = 0; j < args.length; ++j) {
+ int t = type(cw, args[j].getDescriptor());
+ inputLocals[i++] = t;
+ if (t == LONG || t == DOUBLE) {
+ inputLocals[i++] = TOP;
+ }
+ }
+ while (i < maxLocals) {
+ inputLocals[i++] = TOP;
+ }
+ }
+
+ /**
+ * Simulates the action of the given instruction on the output stack frame.
+ *
+ * @param opcode
+ * the opcode of the instruction.
+ * @param arg
+ * the operand of the instruction, if any.
+ * @param cw
+ * the class writer to which this label belongs.
+ * @param item
+ * the operand of the instructions, if any.
+ */
+ void execute(final int opcode, final int arg, final ClassWriter cw,
+ final Item item) {
+ int t1, t2, t3, t4;
+ switch (opcode) {
+ case Opcodes.NOP:
+ case Opcodes.INEG:
+ case Opcodes.LNEG:
+ case Opcodes.FNEG:
+ case Opcodes.DNEG:
+ case Opcodes.I2B:
+ case Opcodes.I2C:
+ case Opcodes.I2S:
+ case Opcodes.GOTO:
+ case Opcodes.RETURN:
+ break;
+ case Opcodes.ACONST_NULL:
+ push(NULL);
+ break;
+ case Opcodes.ICONST_M1:
+ case Opcodes.ICONST_0:
+ case Opcodes.ICONST_1:
+ case Opcodes.ICONST_2:
+ case Opcodes.ICONST_3:
+ case Opcodes.ICONST_4:
+ case Opcodes.ICONST_5:
+ case Opcodes.BIPUSH:
+ case Opcodes.SIPUSH:
+ case Opcodes.ILOAD:
+ push(INTEGER);
+ break;
+ case Opcodes.LCONST_0:
+ case Opcodes.LCONST_1:
+ case Opcodes.LLOAD:
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FCONST_0:
+ case Opcodes.FCONST_1:
+ case Opcodes.FCONST_2:
+ case Opcodes.FLOAD:
+ push(FLOAT);
+ break;
+ case Opcodes.DCONST_0:
+ case Opcodes.DCONST_1:
+ case Opcodes.DLOAD:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LDC:
+ switch (item.type) {
+ case ClassWriter.INT:
+ push(INTEGER);
+ break;
+ case ClassWriter.LONG:
+ push(LONG);
+ push(TOP);
+ break;
+ case ClassWriter.FLOAT:
+ push(FLOAT);
+ break;
+ case ClassWriter.DOUBLE:
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case ClassWriter.CLASS:
+ push(OBJECT | cw.addType("java/lang/Class"));
+ break;
+ case ClassWriter.STR:
+ push(OBJECT | cw.addType("java/lang/String"));
+ break;
+ case ClassWriter.MTYPE:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodType"));
+ break;
+ // case ClassWriter.HANDLE_BASE + [1..9]:
+ default:
+ push(OBJECT | cw.addType("java/lang/invoke/MethodHandle"));
+ }
+ break;
+ case Opcodes.ALOAD:
+ push(get(arg));
+ break;
+ case Opcodes.IALOAD:
+ case Opcodes.BALOAD:
+ case Opcodes.CALOAD:
+ case Opcodes.SALOAD:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LALOAD:
+ case Opcodes.D2L:
+ pop(2);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FALOAD:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DALOAD:
+ case Opcodes.L2D:
+ pop(2);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.AALOAD:
+ pop(1);
+ t1 = pop();
+ push(ELEMENT_OF + t1);
+ break;
+ case Opcodes.ISTORE:
+ case Opcodes.FSTORE:
+ case Opcodes.ASTORE:
+ t1 = pop();
+ set(arg, t1);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+ }
+ }
+ break;
+ case Opcodes.LSTORE:
+ case Opcodes.DSTORE:
+ pop(1);
+ t1 = pop();
+ set(arg, t1);
+ set(arg + 1, TOP);
+ if (arg > 0) {
+ t2 = get(arg - 1);
+ // if t2 is of kind STACK or LOCAL we cannot know its size!
+ if (t2 == LONG || t2 == DOUBLE) {
+ set(arg - 1, TOP);
+ } else if ((t2 & KIND) != BASE) {
+ set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);
+ }
+ }
+ break;
+ case Opcodes.IASTORE:
+ case Opcodes.BASTORE:
+ case Opcodes.CASTORE:
+ case Opcodes.SASTORE:
+ case Opcodes.FASTORE:
+ case Opcodes.AASTORE:
+ pop(3);
+ break;
+ case Opcodes.LASTORE:
+ case Opcodes.DASTORE:
+ pop(4);
+ break;
+ case Opcodes.POP:
+ case Opcodes.IFEQ:
+ case Opcodes.IFNE:
+ case Opcodes.IFLT:
+ case Opcodes.IFGE:
+ case Opcodes.IFGT:
+ case Opcodes.IFLE:
+ case Opcodes.IRETURN:
+ case Opcodes.FRETURN:
+ case Opcodes.ARETURN:
+ case Opcodes.TABLESWITCH:
+ case Opcodes.LOOKUPSWITCH:
+ case Opcodes.ATHROW:
+ case Opcodes.MONITORENTER:
+ case Opcodes.MONITOREXIT:
+ case Opcodes.IFNULL:
+ case Opcodes.IFNONNULL:
+ pop(1);
+ break;
+ case Opcodes.POP2:
+ case Opcodes.IF_ICMPEQ:
+ case Opcodes.IF_ICMPNE:
+ case Opcodes.IF_ICMPLT:
+ case Opcodes.IF_ICMPGE:
+ case Opcodes.IF_ICMPGT:
+ case Opcodes.IF_ICMPLE:
+ case Opcodes.IF_ACMPEQ:
+ case Opcodes.IF_ACMPNE:
+ case Opcodes.LRETURN:
+ case Opcodes.DRETURN:
+ pop(2);
+ break;
+ case Opcodes.DUP:
+ t1 = pop();
+ push(t1);
+ push(t1);
+ break;
+ case Opcodes.DUP_X1:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2:
+ t1 = pop();
+ t2 = pop();
+ push(t2);
+ push(t1);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X1:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ push(t2);
+ push(t1);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.DUP2_X2:
+ t1 = pop();
+ t2 = pop();
+ t3 = pop();
+ t4 = pop();
+ push(t2);
+ push(t1);
+ push(t4);
+ push(t3);
+ push(t2);
+ push(t1);
+ break;
+ case Opcodes.SWAP:
+ t1 = pop();
+ t2 = pop();
+ push(t1);
+ push(t2);
+ break;
+ case Opcodes.IADD:
+ case Opcodes.ISUB:
+ case Opcodes.IMUL:
+ case Opcodes.IDIV:
+ case Opcodes.IREM:
+ case Opcodes.IAND:
+ case Opcodes.IOR:
+ case Opcodes.IXOR:
+ case Opcodes.ISHL:
+ case Opcodes.ISHR:
+ case Opcodes.IUSHR:
+ case Opcodes.L2I:
+ case Opcodes.D2I:
+ case Opcodes.FCMPL:
+ case Opcodes.FCMPG:
+ pop(2);
+ push(INTEGER);
+ break;
+ case Opcodes.LADD:
+ case Opcodes.LSUB:
+ case Opcodes.LMUL:
+ case Opcodes.LDIV:
+ case Opcodes.LREM:
+ case Opcodes.LAND:
+ case Opcodes.LOR:
+ case Opcodes.LXOR:
+ pop(4);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.FADD:
+ case Opcodes.FSUB:
+ case Opcodes.FMUL:
+ case Opcodes.FDIV:
+ case Opcodes.FREM:
+ case Opcodes.L2F:
+ case Opcodes.D2F:
+ pop(2);
+ push(FLOAT);
+ break;
+ case Opcodes.DADD:
+ case Opcodes.DSUB:
+ case Opcodes.DMUL:
+ case Opcodes.DDIV:
+ case Opcodes.DREM:
+ pop(4);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.LSHL:
+ case Opcodes.LSHR:
+ case Opcodes.LUSHR:
+ pop(3);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.IINC:
+ set(arg, INTEGER);
+ break;
+ case Opcodes.I2L:
+ case Opcodes.F2L:
+ pop(1);
+ push(LONG);
+ push(TOP);
+ break;
+ case Opcodes.I2F:
+ pop(1);
+ push(FLOAT);
+ break;
+ case Opcodes.I2D:
+ case Opcodes.F2D:
+ pop(1);
+ push(DOUBLE);
+ push(TOP);
+ break;
+ case Opcodes.F2I:
+ case Opcodes.ARRAYLENGTH:
+ case Opcodes.INSTANCEOF:
+ pop(1);
+ push(INTEGER);
+ break;
+ case Opcodes.LCMP:
+ case Opcodes.DCMPL:
+ case Opcodes.DCMPG:
+ pop(4);
+ push(INTEGER);
+ break;
+ case Opcodes.JSR:
+ case Opcodes.RET:
+ throw new RuntimeException(
+ "JSR/RET are not supported with computeFrames option");
+ case Opcodes.GETSTATIC:
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTSTATIC:
+ pop(item.strVal3);
+ break;
+ case Opcodes.GETFIELD:
+ pop(1);
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.PUTFIELD:
+ pop(item.strVal3);
+ pop();
+ break;
+ case Opcodes.INVOKEVIRTUAL:
+ case Opcodes.INVOKESPECIAL:
+ case Opcodes.INVOKESTATIC:
+ case Opcodes.INVOKEINTERFACE:
+ pop(item.strVal3);
+ if (opcode != Opcodes.INVOKESTATIC) {
+ t1 = pop();
+ if (opcode == Opcodes.INVOKESPECIAL
+ && item.strVal2.charAt(0) == '<') {
+ init(t1);
+ }
+ }
+ push(cw, item.strVal3);
+ break;
+ case Opcodes.INVOKEDYNAMIC:
+ pop(item.strVal2);
+ push(cw, item.strVal2);
+ break;
+ case Opcodes.NEW:
+ push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));
+ break;
+ case Opcodes.NEWARRAY:
+ pop();
+ switch (arg) {
+ case Opcodes.T_BOOLEAN:
+ push(ARRAY_OF | BOOLEAN);
+ break;
+ case Opcodes.T_CHAR:
+ push(ARRAY_OF | CHAR);
+ break;
+ case Opcodes.T_BYTE:
+ push(ARRAY_OF | BYTE);
+ break;
+ case Opcodes.T_SHORT:
+ push(ARRAY_OF | SHORT);
+ break;
+ case Opcodes.T_INT:
+ push(ARRAY_OF | INTEGER);
+ break;
+ case Opcodes.T_FLOAT:
+ push(ARRAY_OF | FLOAT);
+ break;
+ case Opcodes.T_DOUBLE:
+ push(ARRAY_OF | DOUBLE);
+ break;
+ // case Opcodes.T_LONG:
+ default:
+ push(ARRAY_OF | LONG);
+ break;
+ }
+ break;
+ case Opcodes.ANEWARRAY:
+ String s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, '[' + s);
+ } else {
+ push(ARRAY_OF | OBJECT | cw.addType(s));
+ }
+ break;
+ case Opcodes.CHECKCAST:
+ s = item.strVal1;
+ pop();
+ if (s.charAt(0) == '[') {
+ push(cw, s);
+ } else {
+ push(OBJECT | cw.addType(s));
+ }
+ break;
+ // case Opcodes.MULTIANEWARRAY:
+ default:
+ pop(arg);
+ push(cw, item.strVal1);
+ break;
+ }
+ }
+
+ /**
+ * Merges the input frame of the given basic block with the input and output
+ * frames of this basic block. Returns <tt>true</tt> if the input frame of
+ * the given label has been changed by this operation.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param frame
+ * the basic block whose input frame must be updated.
+ * @param edge
+ * the kind of the {@link Edge} between this label and 'label'.
+ * See {@link Edge#info}.
+ * @return <tt>true</tt> if the input frame of the given label has been
+ * changed by this operation.
+ */
+ boolean merge(final ClassWriter cw, final Frame frame, final int edge) {
+ boolean changed = false;
+ int i, s, dim, kind, t;
+
+ int nLocal = inputLocals.length;
+ int nStack = inputStack.length;
+ if (frame.inputLocals == null) {
+ frame.inputLocals = new int[nLocal];
+ changed = true;
+ }
+
+ for (i = 0; i < nLocal; ++i) {
+ if (outputLocals != null && i < outputLocals.length) {
+ s = outputLocals[i];
+ if (s == 0) {
+ t = inputLocals[i];
+ } else {
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == BASE) {
+ t = s;
+ } else {
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ }
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
+ t = TOP;
+ }
+ }
+ }
+ } else {
+ t = inputLocals[i];
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+
+ if (edge > 0) {
+ for (i = 0; i < nLocal; ++i) {
+ t = inputLocals[i];
+ changed |= merge(cw, t, frame.inputLocals, i);
+ }
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[1];
+ changed = true;
+ }
+ changed |= merge(cw, edge, frame.inputStack, 0);
+ return changed;
+ }
+
+ int nInputStack = inputStack.length + owner.inputStackTop;
+ if (frame.inputStack == null) {
+ frame.inputStack = new int[nInputStack + outputStackTop];
+ changed = true;
+ }
+
+ for (i = 0; i < nInputStack; ++i) {
+ t = inputStack[i];
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, i);
+ }
+ for (i = 0; i < outputStackTop; ++i) {
+ s = outputStack[i];
+ dim = s & DIM;
+ kind = s & KIND;
+ if (kind == BASE) {
+ t = s;
+ } else {
+ if (kind == LOCAL) {
+ t = dim + inputLocals[s & VALUE];
+ } else {
+ t = dim + inputStack[nStack - (s & VALUE)];
+ }
+ if ((s & TOP_IF_LONG_OR_DOUBLE) != 0
+ && (t == LONG || t == DOUBLE)) {
+ t = TOP;
+ }
+ }
+ if (initializations != null) {
+ t = init(cw, t);
+ }
+ changed |= merge(cw, t, frame.inputStack, nInputStack + i);
+ }
+ return changed;
+ }
+
+ /**
+ * Merges the type at the given index in the given type array with the given
+ * type. Returns <tt>true</tt> if the type array has been modified by this
+ * operation.
+ *
+ * @param cw
+ * the ClassWriter to which this label belongs.
+ * @param t
+ * the type with which the type array element must be merged.
+ * @param types
+ * an array of types.
+ * @param index
+ * the index of the type that must be merged in 'types'.
+ * @return <tt>true</tt> if the type array has been modified by this
+ * operation.
+ */
+ private static boolean merge(final ClassWriter cw, int t,
+ final int[] types, final int index) {
+ int u = types[index];
+ if (u == t) {
+ // if the types are equal, merge(u,t)=u, so there is no change
+ return false;
+ }
+ if ((t & ~DIM) == NULL) {
+ if (u == NULL) {
+ return false;
+ }
+ t = NULL;
+ }
+ if (u == 0) {
+ // if types[index] has never been assigned, merge(u,t)=t
+ types[index] = t;
+ return true;
+ }
+ int v;
+ if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {
+ // if u is a reference type of any dimension
+ if (t == NULL) {
+ // if t is the NULL type, merge(u,t)=u, so there is no change
+ return false;
+ } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {
+ // if t and u have the same dimension and same base kind
+ if ((u & BASE_KIND) == OBJECT) {
+ // if t is also a reference type, and if u and t have the
+ // same dimension merge(u,t) = dim(t) | common parent of the
+ // element types of u and t
+ v = (t & DIM) | OBJECT
+ | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);
+ } else {
+ // if u and t are array types, but not with the same element
+ // type, merge(u,t) = dim(u) - 1 | java/lang/Object
+ int vdim = ELEMENT_OF + (u & DIM);
+ v = vdim | OBJECT | cw.addType("java/lang/Object");
+ }
+ } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {
+ // if t is any other reference or array type, the merged type
+ // is min(udim, tdim) | java/lang/Object, where udim is the
+ // array dimension of u, minus 1 if u is an array type with a
+ // primitive element type (and similarly for tdim).
+ int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0
+ : ELEMENT_OF) + (t & DIM);
+ int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0
+ : ELEMENT_OF) + (u & DIM);
+ v = Math.min(tdim, udim) | OBJECT
+ | cw.addType("java/lang/Object");
+ } else {
+ // if t is any other type, merge(u,t)=TOP
+ v = TOP;
+ }
+ } else if (u == NULL) {
+ // if u is the NULL type, merge(u,t)=t,
+ // or TOP if t is not a reference type
+ v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;
+ } else {
+ // if u is any other type, merge(u,t)=TOP whatever t
+ v = TOP;
+ }
+ if (u != v) {
+ types[index] = v;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handle.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handle.java
new file mode 100644
index 0000000..9b1c481
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handle.java
@@ -0,0 +1,170 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.powermock.objectweb.asm;
+
+/**
+ * A reference to a field or a method.
+ *
+ * @author Remi Forax
+ * @author Eric Bruneton
+ */
+public final class Handle {
+
+ /**
+ * The kind of field or method designated by this Handle. Should be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ final int tag;
+
+ /**
+ * The internal name of the class that owns the field or method designated
+ * by this handle.
+ */
+ final String owner;
+
+ /**
+ * The name of the field or method designated by this handle.
+ */
+ final String name;
+
+ /**
+ * The descriptor of the field or method designated by this handle.
+ */
+ final String desc;
+
+ /**
+ * Constructs a new field or method handle.
+ *
+ * @param tag
+ * the kind of field or method designated by this Handle. Must be
+ * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL},
+ * {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ * @param owner
+ * the internal name of the class that owns the field or method
+ * designated by this handle.
+ * @param name
+ * the name of the field or method designated by this handle.
+ * @param desc
+ * the descriptor of the field or method designated by this
+ * handle.
+ */
+ public Handle(int tag, String owner, String name, String desc) {
+ this.tag = tag;
+ this.owner = owner;
+ this.name = name;
+ this.desc = desc;
+ }
+
+ /**
+ * Returns the kind of field or method designated by this handle.
+ *
+ * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},
+ * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},
+ * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},
+ * {@link Opcodes#H_INVOKESPECIAL},
+ * {@link Opcodes#H_NEWINVOKESPECIAL} or
+ * {@link Opcodes#H_INVOKEINTERFACE}.
+ */
+ public int getTag() {
+ return tag;
+ }
+
+ /**
+ * Returns the internal name of the class that owns the field or method
+ * designated by this handle.
+ *
+ * @return the internal name of the class that owns the field or method
+ * designated by this handle.
+ */
+ public String getOwner() {
+ return owner;
+ }
+
+ /**
+ * Returns the name of the field or method designated by this handle.
+ *
+ * @return the name of the field or method designated by this handle.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the descriptor of the field or method designated by this handle.
+ *
+ * @return the descriptor of the field or method designated by this handle.
+ */
+ public String getDesc() {
+ return desc;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (!(obj instanceof Handle)) {
+ return false;
+ }
+ Handle h = (Handle) obj;
+ return tag == h.tag && owner.equals(h.owner) && name.equals(h.name)
+ && desc.equals(h.desc);
+ }
+
+ @Override
+ public int hashCode() {
+ return tag + owner.hashCode() * name.hashCode() * desc.hashCode();
+ }
+
+ /**
+ * Returns the textual representation of this handle. The textual
+ * representation is:
+ *
+ * <pre>
+ * owner '.' name desc ' ' '(' tag ')'
+ * </pre>
+ *
+ * . As this format is unambiguous, it can be parsed if necessary.
+ */
+ @Override
+ public String toString() {
+ return owner + '.' + name + desc + " (" + tag + ')';
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handler.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handler.java
new file mode 100644
index 0000000..6f3c8d8
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Handler.java
@@ -0,0 +1,121 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * Information about an exception handler block.
+ *
+ * @author Eric Bruneton
+ */
+class Handler {
+
+ /**
+ * Beginning of the exception handler's scope (inclusive).
+ */
+ Label start;
+
+ /**
+ * End of the exception handler's scope (exclusive).
+ */
+ Label end;
+
+ /**
+ * Beginning of the exception handler's code.
+ */
+ Label handler;
+
+ /**
+ * Internal name of the type of exceptions handled by this handler, or
+ * <tt>null</tt> to catch any exceptions.
+ */
+ String desc;
+
+ /**
+ * Constant pool index of the internal name of the type of exceptions
+ * handled by this handler, or 0 to catch any exceptions.
+ */
+ int type;
+
+ /**
+ * Next exception handler block info.
+ */
+ Handler next;
+
+ /**
+ * Removes the range between start and end from the given exception
+ * handlers.
+ *
+ * @param h
+ * an exception handler list.
+ * @param start
+ * the start of the range to be removed.
+ * @param end
+ * the end of the range to be removed. Maybe null.
+ * @return the exception handler list with the start-end range removed.
+ */
+ static Handler remove(Handler h, Label start, Label end) {
+ if (h == null) {
+ return null;
+ } else {
+ h.next = remove(h.next, start, end);
+ }
+ int hstart = h.start.position;
+ int hend = h.end.position;
+ int s = start.position;
+ int e = end == null ? Integer.MAX_VALUE : end.position;
+ // if [hstart,hend[ and [s,e[ intervals intersect...
+ if (s < hend && e > hstart) {
+ if (s <= hstart) {
+ if (e >= hend) {
+ // [hstart,hend[ fully included in [s,e[, h removed
+ h = h.next;
+ } else {
+ // [hstart,hend[ minus [s,e[ = [e,hend[
+ h.start = end;
+ }
+ } else if (e >= hend) {
+ // [hstart,hend[ minus [s,e[ = [hstart,s[
+ h.end = start;
+ } else {
+ // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[
+ Handler g = new Handler();
+ g.start = end;
+ g.end = h.end;
+ g.handler = h.handler;
+ g.desc = h.desc;
+ g.type = h.type;
+ g.next = h.next;
+ h.end = start;
+ h.next = g;
+ }
+ }
+ return h;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Item.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Item.java
new file mode 100644
index 0000000..390722a
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Item.java
@@ -0,0 +1,313 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A constant pool item. Constant pool items can be created with the 'newXXX'
+ * methods in the {@link ClassWriter} class.
+ *
+ * @author Eric Bruneton
+ */
+final class Item {
+
+ /**
+ * Index of this item in the constant pool.
+ */
+ int index;
+
+ /**
+ * Type of this constant pool item. A single class is used to represent all
+ * constant pool item types, in order to minimize the bytecode size of this
+ * package. The value of this field is one of {@link ClassWriter#INT},
+ * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},
+ * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},
+ * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},
+ * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},
+ * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},
+ * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.
+ *
+ * MethodHandle constant 9 variations are stored using a range of 9 values
+ * from {@link ClassWriter#HANDLE_BASE} + 1 to
+ * {@link ClassWriter#HANDLE_BASE} + 9.
+ *
+ * Special Item types are used for Items that are stored in the ClassWriter
+ * {@link ClassWriter#typeTable}, instead of the constant pool, in order to
+ * avoid clashes with normal constant pool items in the ClassWriter constant
+ * pool's hash table. These special item types are
+ * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and
+ * {@link ClassWriter#TYPE_MERGED}.
+ */
+ int type;
+
+ /**
+ * Value of this item, for an integer item.
+ */
+ int intVal;
+
+ /**
+ * Value of this item, for a long item.
+ */
+ long longVal;
+
+ /**
+ * First part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal1;
+
+ /**
+ * Second part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal2;
+
+ /**
+ * Third part of the value of this item, for items that do not hold a
+ * primitive value.
+ */
+ String strVal3;
+
+ /**
+ * The hash code value of this constant pool item.
+ */
+ int hashCode;
+
+ /**
+ * Link to another constant pool item, used for collision lists in the
+ * constant pool's hash table.
+ */
+ Item next;
+
+ /**
+ * Constructs an uninitialized {@link Item}.
+ */
+ Item() {
+ }
+
+ /**
+ * Constructs an uninitialized {@link Item} for constant pool element at
+ * given position.
+ *
+ * @param index
+ * index of the item to be constructed.
+ */
+ Item(final int index) {
+ this.index = index;
+ }
+
+ /**
+ * Constructs a copy of the given item.
+ *
+ * @param index
+ * index of the item to be constructed.
+ * @param i
+ * the item that must be copied into the item to be constructed.
+ */
+ Item(final int index, final Item i) {
+ this.index = index;
+ type = i.type;
+ intVal = i.intVal;
+ longVal = i.longVal;
+ strVal1 = i.strVal1;
+ strVal2 = i.strVal2;
+ strVal3 = i.strVal3;
+ hashCode = i.hashCode;
+ }
+
+ /**
+ * Sets this item to an integer item.
+ *
+ * @param intVal
+ * the value of this item.
+ */
+ void set(final int intVal) {
+ this.type = ClassWriter.INT;
+ this.intVal = intVal;
+ this.hashCode = 0x7FFFFFFF & (type + intVal);
+ }
+
+ /**
+ * Sets this item to a long item.
+ *
+ * @param longVal
+ * the value of this item.
+ */
+ void set(final long longVal) {
+ this.type = ClassWriter.LONG;
+ this.longVal = longVal;
+ this.hashCode = 0x7FFFFFFF & (type + (int) longVal);
+ }
+
+ /**
+ * Sets this item to a float item.
+ *
+ * @param floatVal
+ * the value of this item.
+ */
+ void set(final float floatVal) {
+ this.type = ClassWriter.FLOAT;
+ this.intVal = Float.floatToRawIntBits(floatVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);
+ }
+
+ /**
+ * Sets this item to a double item.
+ *
+ * @param doubleVal
+ * the value of this item.
+ */
+ void set(final double doubleVal) {
+ this.type = ClassWriter.DOUBLE;
+ this.longVal = Double.doubleToRawLongBits(doubleVal);
+ this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);
+ }
+
+ /**
+ * Sets this item to an item that do not hold a primitive value.
+ *
+ * @param type
+ * the type of this item.
+ * @param strVal1
+ * first part of the value of this item.
+ * @param strVal2
+ * second part of the value of this item.
+ * @param strVal3
+ * third part of the value of this item.
+ */
+ @SuppressWarnings("fallthrough")
+ void set(final int type, final String strVal1, final String strVal2,
+ final String strVal3) {
+ this.type = type;
+ this.strVal1 = strVal1;
+ this.strVal2 = strVal2;
+ this.strVal3 = strVal3;
+ switch (type) {
+ case ClassWriter.CLASS:
+ this.intVal = 0; // intVal of a class must be zero, see visitInnerClass
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());
+ return;
+ case ClassWriter.NAME_TYPE: {
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode());
+ return;
+ }
+ // ClassWriter.FIELD:
+ // ClassWriter.METH:
+ // ClassWriter.IMETH:
+ // ClassWriter.HANDLE_BASE + 1..9
+ default:
+ hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()
+ * strVal2.hashCode() * strVal3.hashCode());
+ }
+ }
+
+ /**
+ * Sets the item to an InvokeDynamic item.
+ *
+ * @param name
+ * invokedynamic's name.
+ * @param desc
+ * invokedynamic's desc.
+ * @param bsmIndex
+ * zero based index into the class attribute BootrapMethods.
+ */
+ void set(String name, String desc, int bsmIndex) {
+ this.type = ClassWriter.INDY;
+ this.longVal = bsmIndex;
+ this.strVal1 = name;
+ this.strVal2 = desc;
+ this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex
+ * strVal1.hashCode() * strVal2.hashCode());
+ }
+
+ /**
+ * Sets the item to a BootstrapMethod item.
+ *
+ * @param position
+ * position in byte in the class attribute BootrapMethods.
+ * @param hashCode
+ * hashcode of the item. This hashcode is processed from the
+ * hashcode of the bootstrap method and the hashcode of all
+ * bootstrap arguments.
+ */
+ void set(int position, int hashCode) {
+ this.type = ClassWriter.BSM;
+ this.intVal = position;
+ this.hashCode = hashCode;
+ }
+
+ /**
+ * Indicates if the given item is equal to this one. <i>This method assumes
+ * that the two items have the same {@link #type}</i>.
+ *
+ * @param i
+ * the item to be compared to this one. Both items must have the
+ * same {@link #type}.
+ * @return <tt>true</tt> if the given item if equal to this one,
+ * <tt>false</tt> otherwise.
+ */
+ boolean isEqualTo(final Item i) {
+ switch (type) {
+ case ClassWriter.UTF8:
+ case ClassWriter.STR:
+ case ClassWriter.CLASS:
+ case ClassWriter.MTYPE:
+ case ClassWriter.TYPE_NORMAL:
+ return i.strVal1.equals(strVal1);
+ case ClassWriter.TYPE_MERGED:
+ case ClassWriter.LONG:
+ case ClassWriter.DOUBLE:
+ return i.longVal == longVal;
+ case ClassWriter.INT:
+ case ClassWriter.FLOAT:
+ return i.intVal == intVal;
+ case ClassWriter.TYPE_UNINIT:
+ return i.intVal == intVal && i.strVal1.equals(strVal1);
+ case ClassWriter.NAME_TYPE:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);
+ case ClassWriter.INDY: {
+ return i.longVal == longVal && i.strVal1.equals(strVal1)
+ && i.strVal2.equals(strVal2);
+ }
+ // case ClassWriter.FIELD:
+ // case ClassWriter.METH:
+ // case ClassWriter.IMETH:
+ // case ClassWriter.HANDLE_BASE + 1..9
+ default:
+ return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)
+ && i.strVal3.equals(strVal3);
+ }
+ }
+
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/LICENSE.txt b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/LICENSE.txt
new file mode 100644
index 0000000..4d19185
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/LICENSE.txt
@@ -0,0 +1,28 @@
+
+ ASM: a very small and fast Java bytecode manipulation framework
+ Copyright (c) 2000-2011 INRIA, France Telecom
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Label.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Label.java
new file mode 100644
index 0000000..38ca686
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Label.java
@@ -0,0 +1,565 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A label represents a position in the bytecode of a method. Labels are used
+ * for jump, goto, and switch instructions, and for try catch blocks. A label
+ * designates the <i>instruction</i> that is just after. Note however that there
+ * can be other elements between a label and the instruction it designates (such
+ * as other labels, stack map frames, line numbers, etc.).
+ *
+ * @author Eric Bruneton
+ */
+public class Label {
+
+ /**
+ * Indicates if this label is only used for debug attributes. Such a label
+ * is not the start of a basic block, the target of a jump instruction, or
+ * an exception handler. It can be safely ignored in control flow graph
+ * analysis algorithms (for optimization purposes).
+ */
+ static final int DEBUG = 1;
+
+ /**
+ * Indicates if the position of this label is known.
+ */
+ static final int RESOLVED = 2;
+
+ /**
+ * Indicates if this label has been updated, after instruction resizing.
+ */
+ static final int RESIZED = 4;
+
+ /**
+ * Indicates if this basic block has been pushed in the basic block stack.
+ * See {@link MethodWriter#visitMaxs visitMaxs}.
+ */
+ static final int PUSHED = 8;
+
+ /**
+ * Indicates if this label is the target of a jump instruction, or the start
+ * of an exception handler.
+ */
+ static final int TARGET = 16;
+
+ /**
+ * Indicates if a stack map frame must be stored for this label.
+ */
+ static final int STORE = 32;
+
+ /**
+ * Indicates if this label corresponds to a reachable basic block.
+ */
+ static final int REACHABLE = 64;
+
+ /**
+ * Indicates if this basic block ends with a JSR instruction.
+ */
+ static final int JSR = 128;
+
+ /**
+ * Indicates if this basic block ends with a RET instruction.
+ */
+ static final int RET = 256;
+
+ /**
+ * Indicates if this basic block is the start of a subroutine.
+ */
+ static final int SUBROUTINE = 512;
+
+ /**
+ * Indicates if this subroutine basic block has been visited by a
+ * visitSubroutine(null, ...) call.
+ */
+ static final int VISITED = 1024;
+
+ /**
+ * Indicates if this subroutine basic block has been visited by a
+ * visitSubroutine(!null, ...) call.
+ */
+ static final int VISITED2 = 2048;
+
+ /**
+ * Field used to associate user information to a label. Warning: this field
+ * is used by the ASM tree package. In order to use it with the ASM tree
+ * package you must override the
+ * {@link org.objectweb.asm.tree.MethodNode#getLabelNode} method.
+ */
+ public Object info;
+
+ /**
+ * Flags that indicate the status of this label.
+ *
+ * @see #DEBUG
+ * @see #RESOLVED
+ * @see #RESIZED
+ * @see #PUSHED
+ * @see #TARGET
+ * @see #STORE
+ * @see #REACHABLE
+ * @see #JSR
+ * @see #RET
+ */
+ int status;
+
+ /**
+ * The line number corresponding to this label, if known. If there are
+ * several lines, each line is stored in a separate label, all linked via
+ * their next field (these links are created in ClassReader and removed just
+ * before visitLabel is called, so that this does not impact the rest of the
+ * code).
+ */
+ int line;
+
+ /**
+ * The position of this label in the code, if known.
+ */
+ int position;
+
+ /**
+ * Number of forward references to this label, times two.
+ */
+ private int referenceCount;
+
+ /**
+ * Informations about forward references. Each forward reference is
+ * described by two consecutive integers in this array: the first one is the
+ * position of the first byte of the bytecode instruction that contains the
+ * forward reference, while the second is the position of the first byte of
+ * the forward reference itself. In fact the sign of the first integer
+ * indicates if this reference uses 2 or 4 bytes, and its absolute value
+ * gives the position of the bytecode instruction. This array is also used
+ * as a bitset to store the subroutines to which a basic block belongs. This
+ * information is needed in {@linked MethodWriter#visitMaxs}, after all
+ * forward references have been resolved. Hence the same array can be used
+ * for both purposes without problems.
+ */
+ private int[] srcAndRefPositions;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow and data flow graph analysis algorithms (used
+ * to compute the maximum stack size or the stack map frames). A control
+ * flow graph contains one node per "basic block", and one edge per "jump"
+ * from one basic block to another. Each node (i.e., each basic block) is
+ * represented by the Label object that corresponds to the first instruction
+ * of this basic block. Each node also stores the list of its successors in
+ * the graph, as a linked list of Edge objects.
+ *
+ * The control flow analysis algorithms used to compute the maximum stack
+ * size or the stack map frames are similar and use two steps. The first
+ * step, during the visit of each instruction, builds information about the
+ * state of the local variables and the operand stack at the end of each
+ * basic block, called the "output frame", <i>relatively</i> to the frame
+ * state at the beginning of the basic block, which is called the "input
+ * frame", and which is <i>unknown</i> during this step. The second step, in
+ * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes
+ * information about the input frame of each basic block, from the input
+ * state of the first basic block (known from the method signature), and by
+ * the using the previously computed relative output frames.
+ *
+ * The algorithm used to compute the maximum stack size only computes the
+ * relative output and absolute input stack heights, while the algorithm
+ * used to compute stack map frames computes relative output frames and
+ * absolute input frames.
+ */
+
+ /**
+ * Start of the output stack relatively to the input stack. The exact
+ * semantics of this field depends on the algorithm that is used.
+ *
+ * When only the maximum stack size is computed, this field is the number of
+ * elements in the input stack.
+ *
+ * When the stack map frames are completely computed, this field is the
+ * offset of the first output stack element relatively to the top of the
+ * input stack. This offset is always negative or null. A null offset means
+ * that the output stack must be appended to the input stack. A -n offset
+ * means that the first n output stack elements must replace the top n input
+ * stack elements, and that the other elements must be appended to the input
+ * stack.
+ */
+ int inputStackTop;
+
+ /**
+ * Maximum height reached by the output stack, relatively to the top of the
+ * input stack. This maximum is always positive or null.
+ */
+ int outputStackMax;
+
+ /**
+ * Information about the input and output stack map frames of this basic
+ * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}
+ * option is used.
+ */
+ Frame frame;
+
+ /**
+ * The successor of this label, in the order they are visited. This linked
+ * list does not include labels used for debug info only. If
+ * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it
+ * does not contain successive labels that denote the same bytecode position
+ * (in this case only the first label appears in this list).
+ */
+ Label successor;
+
+ /**
+ * The successors of this node in the control flow graph. These successors
+ * are stored in a linked list of {@link Edge Edge} objects, linked to each
+ * other by their {@link Edge#next} field.
+ */
+ Edge successors;
+
+ /**
+ * The next basic block in the basic block stack. This stack is used in the
+ * main loop of the fix point algorithm used in the second step of the
+ * control flow analysis algorithms. It is also used in
+ * {@link #visitSubroutine} to avoid using a recursive method, and in
+ * ClassReader to temporarily store multiple source lines for a label.
+ *
+ * @see MethodWriter#visitMaxs
+ */
+ Label next;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new label.
+ */
+ public Label() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods to compute offsets and to manage forward references
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the offset corresponding to this label. This offset is computed
+ * from the start of the method's bytecode. <i>This method is intended for
+ * {@link Attribute} sub classes, and is normally not needed by class
+ * generators or adapters.</i>
+ *
+ * @return the offset corresponding to this label.
+ * @throws IllegalStateException
+ * if this label is not resolved yet.
+ */
+ public int getOffset() {
+ if ((status & RESOLVED) == 0) {
+ throw new IllegalStateException(
+ "Label offset position has not been resolved yet");
+ }
+ return position;
+ }
+
+ /**
+ * Puts a reference to this label in the bytecode of a method. If the
+ * position of the label is known, the offset is computed and written
+ * directly. Otherwise, a null offset is written and a new forward reference
+ * is declared for this label.
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param out
+ * the bytecode of the method.
+ * @param source
+ * the position of first byte of the bytecode instruction that
+ * contains this label.
+ * @param wideOffset
+ * <tt>true</tt> if the reference must be stored in 4 bytes, or
+ * <tt>false</tt> if it must be stored with 2 bytes.
+ * @throws IllegalArgumentException
+ * if this label has not been created by the given code writer.
+ */
+ void put(final MethodWriter owner, final ByteVector out, final int source,
+ final boolean wideOffset) {
+ if ((status & RESOLVED) == 0) {
+ if (wideOffset) {
+ addReference(-1 - source, out.length);
+ out.putInt(-1);
+ } else {
+ addReference(source, out.length);
+ out.putShort(-1);
+ }
+ } else {
+ if (wideOffset) {
+ out.putInt(position - source);
+ } else {
+ out.putShort(position - source);
+ }
+ }
+ }
+
+ /**
+ * Adds a forward reference to this label. This method must be called only
+ * for a true forward reference, i.e. only if this label is not resolved
+ * yet. For backward references, the offset of the reference can be, and
+ * must be, computed and stored directly.
+ *
+ * @param sourcePosition
+ * the position of the referencing instruction. This position
+ * will be used to compute the offset of this forward reference.
+ * @param referencePosition
+ * the position where the offset for this forward reference must
+ * be stored.
+ */
+ private void addReference(final int sourcePosition,
+ final int referencePosition) {
+ if (srcAndRefPositions == null) {
+ srcAndRefPositions = new int[6];
+ }
+ if (referenceCount >= srcAndRefPositions.length) {
+ int[] a = new int[srcAndRefPositions.length + 6];
+ System.arraycopy(srcAndRefPositions, 0, a, 0,
+ srcAndRefPositions.length);
+ srcAndRefPositions = a;
+ }
+ srcAndRefPositions[referenceCount++] = sourcePosition;
+ srcAndRefPositions[referenceCount++] = referencePosition;
+ }
+
+ /**
+ * Resolves all forward references to this label. This method must be called
+ * when this label is added to the bytecode of the method, i.e. when its
+ * position becomes known. This method fills in the blanks that where left
+ * in the bytecode by each forward reference previously added to this label.
+ *
+ * @param owner
+ * the code writer that calls this method.
+ * @param position
+ * the position of this label in the bytecode.
+ * @param data
+ * the bytecode of the method.
+ * @return <tt>true</tt> if a blank that was left for this label was to
+ * small to store the offset. In such a case the corresponding jump
+ * instruction is replaced with a pseudo instruction (using unused
+ * opcodes) using an unsigned two bytes offset. These pseudo
+ * instructions will need to be replaced with true instructions with
+ * wider offsets (4 bytes instead of 2). This is done in
+ * {@link MethodWriter#resizeInstructions}.
+ * @throws IllegalArgumentException
+ * if this label has already been resolved, or if it has not
+ * been created by the given code writer.
+ */
+ boolean resolve(final MethodWriter owner, final int position,
+ final byte[] data) {
+ boolean needUpdate = false;
+ this.status |= RESOLVED;
+ this.position = position;
+ int i = 0;
+ while (i < referenceCount) {
+ int source = srcAndRefPositions[i++];
+ int reference = srcAndRefPositions[i++];
+ int offset;
+ if (source >= 0) {
+ offset = position - source;
+ if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
+ /*
+ * changes the opcode of the jump instruction, in order to
+ * be able to find it later (see resizeInstructions in
+ * MethodWriter). These temporary opcodes are similar to
+ * jump instruction opcodes, except that the 2 bytes offset
+ * is unsigned (and can therefore represent values from 0 to
+ * 65535, which is sufficient since the size of a method is
+ * limited to 65535 bytes).
+ */
+ int opcode = data[reference - 1] & 0xFF;
+ if (opcode <= Opcodes.JSR) {
+ // changes IFEQ ... JSR to opcodes 202 to 217
+ data[reference - 1] = (byte) (opcode + 49);
+ } else {
+ // changes IFNULL and IFNONNULL to opcodes 218 and 219
+ data[reference - 1] = (byte) (opcode + 20);
+ }
+ needUpdate = true;
+ }
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ } else {
+ offset = position + source + 1;
+ data[reference++] = (byte) (offset >>> 24);
+ data[reference++] = (byte) (offset >>> 16);
+ data[reference++] = (byte) (offset >>> 8);
+ data[reference] = (byte) offset;
+ }
+ }
+ return needUpdate;
+ }
+
+ /**
+ * Returns the first label of the series to which this label belongs. For an
+ * isolated label or for the first label in a series of successive labels,
+ * this method returns the label itself. For other labels it returns the
+ * first label of the series.
+ *
+ * @return the first label of the series to which this label belongs.
+ */
+ Label getFirst() {
+ return !ClassReader.FRAMES || frame == null ? this : frame.owner;
+ }
+
+ // ------------------------------------------------------------------------
+ // Methods related to subroutines
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns true is this basic block belongs to the given subroutine.
+ *
+ * @param id
+ * a subroutine id.
+ * @return true is this basic block belongs to the given subroutine.
+ */
+ boolean inSubroutine(final long id) {
+ if ((status & Label.VISITED) != 0) {
+ return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;
+ }
+ return false;
+ }
+
+ /**
+ * Returns true if this basic block and the given one belong to a common
+ * subroutine.
+ *
+ * @param block
+ * another basic block.
+ * @return true if this basic block and the given one belong to a common
+ * subroutine.
+ */
+ boolean inSameSubroutine(final Label block) {
+ if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {
+ return false;
+ }
+ for (int i = 0; i < srcAndRefPositions.length; ++i) {
+ if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Marks this basic block as belonging to the given subroutine.
+ *
+ * @param id
+ * a subroutine id.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
+ */
+ void addToSubroutine(final long id, final int nbSubroutines) {
+ if ((status & VISITED) == 0) {
+ status |= VISITED;
+ srcAndRefPositions = new int[nbSubroutines / 32 + 1];
+ }
+ srcAndRefPositions[(int) (id >>> 32)] |= (int) id;
+ }
+
+ /**
+ * Finds the basic blocks that belong to a given subroutine, and marks these
+ * blocks as belonging to this subroutine. This method follows the control
+ * flow graph to find all the blocks that are reachable from the current
+ * block WITHOUT following any JSR target.
+ *
+ * @param JSR
+ * a JSR block that jumps to this subroutine. If this JSR is not
+ * null it is added to the successor of the RET blocks found in
+ * the subroutine.
+ * @param id
+ * the id of this subroutine.
+ * @param nbSubroutines
+ * the total number of subroutines in the method.
+ */
+ void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {
+ // user managed stack of labels, to avoid using a recursive method
+ // (recursivity can lead to stack overflow with very large methods)
+ Label stack = this;
+ while (stack != null) {
+ // removes a label l from the stack
+ Label l = stack;
+ stack = l.next;
+ l.next = null;
+
+ if (JSR != null) {
+ if ((l.status & VISITED2) != 0) {
+ continue;
+ }
+ l.status |= VISITED2;
+ // adds JSR to the successors of l, if it is a RET block
+ if ((l.status & RET) != 0) {
+ if (!l.inSameSubroutine(JSR)) {
+ Edge e = new Edge();
+ e.info = l.inputStackTop;
+ e.successor = JSR.successors.successor;
+ e.next = l.successors;
+ l.successors = e;
+ }
+ }
+ } else {
+ // if the l block already belongs to subroutine 'id', continue
+ if (l.inSubroutine(id)) {
+ continue;
+ }
+ // marks the l block as belonging to subroutine 'id'
+ l.addToSubroutine(id, nbSubroutines);
+ }
+ // pushes each successor of l on the stack, except JSR targets
+ Edge e = l.successors;
+ while (e != null) {
+ // if the l block is a JSR block, then 'l.successors.next' leads
+ // to the JSR target (see {@link #visitJumpInsn}) and must
+ // therefore not be followed
+ if ((l.status & Label.JSR) == 0 || e != l.successors.next) {
+ // pushes e.successor on the stack if it not already added
+ if (e.successor.next == null) {
+ e.successor.next = stack;
+ stack = e.successor;
+ }
+ }
+ e = e.next;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Overriden Object methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns a string representation of this label.
+ *
+ * @return a string representation of this label.
+ */
+ @Override
+ public String toString() {
+ return "L" + System.identityHashCode(this);
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodVisitor.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodVisitor.java
new file mode 100644
index 0000000..1258875
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodVisitor.java
@@ -0,0 +1,881 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A visitor to visit a Java method. The methods of this class must be called in
+ * the following order: ( <tt>visitParameter</tt> )* [
+ * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |
+ * <tt>visitParameterAnnotation</tt> <tt>visitTypeAnnotation</tt> |
+ * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |
+ * <tt>visit<i>X</i>Insn</tt> | <tt>visitLabel</tt> |
+ * <tt>visitInsnAnnotation</tt> | <tt>visitTryCatchBlock</tt> |
+ * <tt>visitTryCatchAnnotation</tt> | <tt>visitLocalVariable</tt> |
+ * <tt>visitLocalVariableAnnotation</tt> | <tt>visitLineNumber</tt> )*
+ * <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In addition, the
+ * <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must be called in
+ * the sequential order of the bytecode instructions of the visited code,
+ * <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated
+ * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the
+ * labels passed as arguments have been visited,
+ * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the
+ * corresponding try catch block has been visited, and the
+ * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and
+ * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels
+ * passed as arguments have been visited.
+ *
+ * @author Eric Bruneton
+ */
+public abstract class MethodVisitor {
+
+ /**
+ * The ASM API version implemented by this visitor. The value of this field
+ * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ protected final int api;
+
+ /**
+ * The method visitor to which this visitor must delegate method calls. May
+ * be null.
+ */
+ protected MethodVisitor mv;
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ */
+ public MethodVisitor(final int api) {
+ this(api, null);
+ }
+
+ /**
+ * Constructs a new {@link MethodVisitor}.
+ *
+ * @param api
+ * the ASM API version implemented by this visitor. Must be one
+ * of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+ * @param mv
+ * the method visitor to which this visitor must delegate method
+ * calls. May be null.
+ */
+ public MethodVisitor(final int api, final MethodVisitor mv) {
+ if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {
+ throw new IllegalArgumentException();
+ }
+ this.api = api;
+ this.mv = mv;
+ }
+
+ // -------------------------------------------------------------------------
+ // Parameters, annotations and non standard attributes
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a parameter of this method.
+ *
+ * @param name
+ * parameter name or null if none is provided.
+ * @param access
+ * the parameter's access flags, only <tt>ACC_FINAL</tt>,
+ * <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are
+ * allowed (see {@link Opcodes}).
+ */
+ public void visitParameter(String name, int access) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ mv.visitParameter(name, access);
+ }
+ }
+
+ /**
+ * Visits the default value of this annotation interface method.
+ *
+ * @return a visitor to the visit the actual default value of this
+ * annotation interface method, or <tt>null</tt> if this visitor is
+ * not interested in visiting this default value. The 'name'
+ * parameters passed to the methods of this annotation visitor are
+ * ignored. Moreover, exacly one visit method must be called on this
+ * annotation visitor, followed by visitEnd.
+ */
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (mv != null) {
+ return mv.visitAnnotationDefault();
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation of this method.
+ *
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (mv != null) {
+ return mv.visitAnnotation(desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation on a type in the method signature.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#METHOD_TYPE_PARAMETER
+ * METHOD_TYPE_PARAMETER},
+ * {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND
+ * METHOD_TYPE_PARAMETER_BOUND},
+ * {@link TypeReference#METHOD_RETURN METHOD_RETURN},
+ * {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link TypeReference#METHOD_FORMAL_PARAMETER
+ * METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS
+ * THROWS}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTypeAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits an annotation of a parameter this method.
+ *
+ * @param parameter
+ * the parameter index.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitParameterAnnotation(int parameter,
+ String desc, boolean visible) {
+ if (mv != null) {
+ return mv.visitParameterAnnotation(parameter, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a non standard attribute of this method.
+ *
+ * @param attr
+ * an attribute.
+ */
+ public void visitAttribute(Attribute attr) {
+ if (mv != null) {
+ mv.visitAttribute(attr);
+ }
+ }
+
+ /**
+ * Starts the visit of the method's code, if any (i.e. non abstract method).
+ */
+ public void visitCode() {
+ if (mv != null) {
+ mv.visitCode();
+ }
+ }
+
+ /**
+ * Visits the current state of the local variables and operand stack
+ * elements. This method must(*) be called <i>just before</i> any
+ * instruction <b>i</b> that follows an unconditional branch instruction
+ * such as GOTO or THROW, that is the target of a jump instruction, or that
+ * starts an exception handler block. The visited types must describe the
+ * values of the local variables and of the operand stack elements <i>just
+ * before</i> <b>i</b> is executed.<br>
+ * <br>
+ * (*) this is mandatory only for classes whose version is greater than or
+ * equal to {@link Opcodes#V1_6 V1_6}. <br>
+ * <br>
+ * The frames of a method must be given either in expanded form, or in
+ * compressed form (all frames must use the same format, i.e. you must not
+ * mix expanded and compressed frames within a single method):
+ * <ul>
+ * <li>In expanded form, all frames must have the F_NEW type.</li>
+ * <li>In compressed form, frames are basically "deltas" from the state of
+ * the previous frame:
+ * <ul>
+ * <li>{@link Opcodes#F_SAME} representing frame with exactly the same
+ * locals as the previous frame and with the empty stack.</li>
+ * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same
+ * locals as the previous frame and with single value on the stack (
+ * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the
+ * type of the stack item).</li>
+ * <li>{@link Opcodes#F_APPEND} representing frame with current locals are
+ * the same as the locals in the previous frame, except that additional
+ * locals are defined (<code>nLocal</code> is 1, 2 or 3 and
+ * <code>local</code> elements contains values representing added types).</li>
+ * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the
+ * same as the locals in the previous frame, except that the last 1-3 locals
+ * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>
+ * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>
+ * </ul>
+ * </li>
+ * </ul>
+ * <br>
+ * In both cases the first frame, corresponding to the method's parameters
+ * and access flags, is implicit and must not be visited. Also, it is
+ * illegal to visit two or more frames for the same code location (i.e., at
+ * least one instruction must be visited between two calls to visitFrame).
+ *
+ * @param type
+ * the type of this stack map frame. Must be
+ * {@link Opcodes#F_NEW} for expanded frames, or
+ * {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},
+ * {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or
+ * {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for
+ * compressed frames.
+ * @param nLocal
+ * the number of local variables in the visited frame.
+ * @param local
+ * the local variable types in this frame. This array must not be
+ * modified. Primitive types are represented by
+ * {@link Opcodes#TOP}, {@link Opcodes#INTEGER},
+ * {@link Opcodes#FLOAT}, {@link Opcodes#LONG},
+ * {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or
+ * {@link Opcodes#UNINITIALIZED_THIS} (long and double are
+ * represented by a single element). Reference types are
+ * represented by String objects (representing internal names),
+ * and uninitialized types by Label objects (this label
+ * designates the NEW instruction that created this uninitialized
+ * value).
+ * @param nStack
+ * the number of operand stack elements in the visited frame.
+ * @param stack
+ * the operand stack types in this frame. This array must not be
+ * modified. Its content has the same format as the "local"
+ * array.
+ * @throws IllegalStateException
+ * if a frame is visited just after another one, without any
+ * instruction between the two (unless this frame is a
+ * Opcodes#F_SAME frame, in which case it is silently ignored).
+ */
+ public void visitFrame(int type, int nLocal, Object[] local, int nStack,
+ Object[] stack) {
+ if (mv != null) {
+ mv.visitFrame(type, nLocal, local, nStack, stack);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Normal instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a zero operand instruction.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,
+ * ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,
+ * FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,
+ * LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,
+ * IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,
+ * SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,
+ * DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,
+ * IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,
+ * FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,
+ * IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,
+ * L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,
+ * LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,
+ * DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,
+ * or MONITOREXIT.
+ */
+ public void visitInsn(int opcode) {
+ if (mv != null) {
+ mv.visitInsn(opcode);
+ }
+ }
+
+ /**
+ * Visits an instruction with a single int operand.
+ *
+ * @param opcode
+ * the opcode of the instruction to be visited. This opcode is
+ * either BIPUSH, SIPUSH or NEWARRAY.
+ * @param operand
+ * the operand of the instruction to be visited.<br>
+ * When opcode is BIPUSH, operand value should be between
+ * Byte.MIN_VALUE and Byte.MAX_VALUE.<br>
+ * When opcode is SIPUSH, operand value should be between
+ * Short.MIN_VALUE and Short.MAX_VALUE.<br>
+ * When opcode is NEWARRAY, operand value should be one of
+ * {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},
+ * {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},
+ * {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},
+ * {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.
+ */
+ public void visitIntInsn(int opcode, int operand) {
+ if (mv != null) {
+ mv.visitIntInsn(opcode, operand);
+ }
+ }
+
+ /**
+ * Visits a local variable instruction. A local variable instruction is an
+ * instruction that loads or stores the value of a local variable.
+ *
+ * @param opcode
+ * the opcode of the local variable instruction to be visited.
+ * This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,
+ * ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.
+ * @param var
+ * the operand of the instruction to be visited. This operand is
+ * the index of a local variable.
+ */
+ public void visitVarInsn(int opcode, int var) {
+ if (mv != null) {
+ mv.visitVarInsn(opcode, var);
+ }
+ }
+
+ /**
+ * Visits a type instruction. A type instruction is an instruction that
+ * takes the internal name of a class as parameter.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.
+ * @param type
+ * the operand of the instruction to be visited. This operand
+ * must be the internal name of an object or array class (see
+ * {@link Type#getInternalName() getInternalName}).
+ */
+ public void visitTypeInsn(int opcode, String type) {
+ if (mv != null) {
+ mv.visitTypeInsn(opcode, type);
+ }
+ }
+
+ /**
+ * Visits a field instruction. A field instruction is an instruction that
+ * loads or stores the value of a field of an object.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.
+ * @param owner
+ * the internal name of the field's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the field's name.
+ * @param desc
+ * the field's descriptor (see {@link Type Type}).
+ */
+ public void visitFieldInsn(int opcode, String owner, String name,
+ String desc) {
+ if (mv != null) {
+ mv.visitFieldInsn(opcode, owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ */
+ @Deprecated
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc) {
+ if (api >= Opcodes.ASM5) {
+ boolean itf = opcode == Opcodes.INVOKEINTERFACE;
+ visitMethodInsn(opcode, owner, name, desc, itf);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc);
+ }
+ }
+
+ /**
+ * Visits a method instruction. A method instruction is an instruction that
+ * invokes a method.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or
+ * INVOKEINTERFACE.
+ * @param owner
+ * the internal name of the method's owner class (see
+ * {@link Type#getInternalName() getInternalName}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param itf
+ * if the method's owner class is an interface.
+ */
+ public void visitMethodInsn(int opcode, String owner, String name,
+ String desc, boolean itf) {
+ if (api < Opcodes.ASM5) {
+ if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {
+ throw new IllegalArgumentException(
+ "INVOKESPECIAL/STATIC on interfaces require ASM 5");
+ }
+ visitMethodInsn(opcode, owner, name, desc);
+ return;
+ }
+ if (mv != null) {
+ mv.visitMethodInsn(opcode, owner, name, desc, itf);
+ }
+ }
+
+ /**
+ * Visits an invokedynamic instruction.
+ *
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type Type}).
+ * @param bsm
+ * the bootstrap method.
+ * @param bsmArgs
+ * the bootstrap method constant arguments. Each argument must be
+ * an {@link Integer}, {@link Float}, {@link Long},
+ * {@link Double}, {@link String}, {@link Type} or {@link Handle}
+ * value. This method is allowed to modify the content of the
+ * array so a caller should expect that this array may change.
+ */
+ public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
+ Object... bsmArgs) {
+ if (mv != null) {
+ mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
+ }
+ }
+
+ /**
+ * Visits a jump instruction. A jump instruction is an instruction that may
+ * jump to another instruction.
+ *
+ * @param opcode
+ * the opcode of the type instruction to be visited. This opcode
+ * is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,
+ * IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
+ * IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.
+ * @param label
+ * the operand of the instruction to be visited. This operand is
+ * a label that designates the instruction to which the jump
+ * instruction may jump.
+ */
+ public void visitJumpInsn(int opcode, Label label) {
+ if (mv != null) {
+ mv.visitJumpInsn(opcode, label);
+ }
+ }
+
+ /**
+ * Visits a label. A label designates the instruction that will be visited
+ * just after it.
+ *
+ * @param label
+ * a {@link Label Label} object.
+ */
+ public void visitLabel(Label label) {
+ if (mv != null) {
+ mv.visitLabel(label);
+ }
+ }
+
+ // -------------------------------------------------------------------------
+ // Special instructions
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a LDC instruction. Note that new constant types may be added in
+ * future versions of the Java Virtual Machine. To easily detect new
+ * constant types, implementations of this method should check for
+ * unexpected constant types, like this:
+ *
+ * <pre>
+ * if (cst instanceof Integer) {
+ * // ...
+ * } else if (cst instanceof Float) {
+ * // ...
+ * } else if (cst instanceof Long) {
+ * // ...
+ * } else if (cst instanceof Double) {
+ * // ...
+ * } else if (cst instanceof String) {
+ * // ...
+ * } else if (cst instanceof Type) {
+ * int sort = ((Type) cst).getSort();
+ * if (sort == Type.OBJECT) {
+ * // ...
+ * } else if (sort == Type.ARRAY) {
+ * // ...
+ * } else if (sort == Type.METHOD) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
+ * } else if (cst instanceof Handle) {
+ * // ...
+ * } else {
+ * // throw an exception
+ * }
+ * </pre>
+ *
+ * @param cst
+ * the constant to be loaded on the stack. This parameter must be
+ * a non null {@link Integer}, a {@link Float}, a {@link Long}, a
+ * {@link Double}, a {@link String}, a {@link Type} of OBJECT or
+ * ARRAY sort for <tt>.class</tt> constants, for classes whose
+ * version is 49.0, a {@link Type} of METHOD sort or a
+ * {@link Handle} for MethodType and MethodHandle constants, for
+ * classes whose version is 51.0.
+ */
+ public void visitLdcInsn(Object cst) {
+ if (mv != null) {
+ mv.visitLdcInsn(cst);
+ }
+ }
+
+ /**
+ * Visits an IINC instruction.
+ *
+ * @param var
+ * index of the local variable to be incremented.
+ * @param increment
+ * amount to increment the local variable by.
+ */
+ public void visitIincInsn(int var, int increment) {
+ if (mv != null) {
+ mv.visitIincInsn(var, increment);
+ }
+ }
+
+ /**
+ * Visits a TABLESWITCH instruction.
+ *
+ * @param min
+ * the minimum key value.
+ * @param max
+ * the maximum key value.
+ * @param dflt
+ * beginning of the default handler block.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>min + i</tt> key.
+ */
+ public void visitTableSwitchInsn(int min, int max, Label dflt,
+ Label... labels) {
+ if (mv != null) {
+ mv.visitTableSwitchInsn(min, max, dflt, labels);
+ }
+ }
+
+ /**
+ * Visits a LOOKUPSWITCH instruction.
+ *
+ * @param dflt
+ * beginning of the default handler block.
+ * @param keys
+ * the values of the keys.
+ * @param labels
+ * beginnings of the handler blocks. <tt>labels[i]</tt> is the
+ * beginning of the handler block for the <tt>keys[i]</tt> key.
+ */
+ public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
+ if (mv != null) {
+ mv.visitLookupSwitchInsn(dflt, keys, labels);
+ }
+ }
+
+ /**
+ * Visits a MULTIANEWARRAY instruction.
+ *
+ * @param desc
+ * an array type descriptor (see {@link Type Type}).
+ * @param dims
+ * number of dimensions of the array to allocate.
+ */
+ public void visitMultiANewArrayInsn(String desc, int dims) {
+ if (mv != null) {
+ mv.visitMultiANewArrayInsn(desc, dims);
+ }
+ }
+
+ /**
+ * Visits an annotation on an instruction. This method must be called just
+ * <i>after</i> the annotated instruction. It can be called several times
+ * for the same instruction.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},
+ * {@link TypeReference#NEW NEW},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE
+ * CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE
+ * METHOD_REFERENCE}, {@link TypeReference#CAST CAST},
+ * {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ // -------------------------------------------------------------------------
+ // Exceptions table entries, debug information, max stack and max locals
+ // -------------------------------------------------------------------------
+
+ /**
+ * Visits a try catch block.
+ *
+ * @param start
+ * beginning of the exception handler's scope (inclusive).
+ * @param end
+ * end of the exception handler's scope (exclusive).
+ * @param handler
+ * beginning of the exception handler's code.
+ * @param type
+ * internal name of the type of exceptions handled by the
+ * handler, or <tt>null</tt> to catch any exceptions (for
+ * "finally" blocks).
+ * @throws IllegalArgumentException
+ * if one of the labels has already been visited by this visitor
+ * (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitTryCatchBlock(Label start, Label end, Label handler,
+ String type) {
+ if (mv != null) {
+ mv.visitTryCatchBlock(start, end, handler, type);
+ }
+ }
+
+ /**
+ * Visits an annotation on an exception handler type. This method must be
+ * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated
+ * exception handler. It can be called several times for the same exception
+ * handler.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#EXCEPTION_PARAMETER
+ * EXCEPTION_PARAMETER}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a local variable declaration.
+ *
+ * @param name
+ * the name of a local variable.
+ * @param desc
+ * the type descriptor of this local variable.
+ * @param signature
+ * the type signature of this local variable. May be
+ * <tt>null</tt> if the local variable type does not use generic
+ * types.
+ * @param start
+ * the first instruction corresponding to the scope of this local
+ * variable (inclusive).
+ * @param end
+ * the last instruction corresponding to the scope of this local
+ * variable (exclusive).
+ * @param index
+ * the local variable's index.
+ * @throws IllegalArgumentException
+ * if one of the labels has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitLocalVariable(String name, String desc, String signature,
+ Label start, Label end, int index) {
+ if (mv != null) {
+ mv.visitLocalVariable(name, desc, signature, start, end, index);
+ }
+ }
+
+ /**
+ * Visits an annotation on a local variable type.
+ *
+ * @param typeRef
+ * a reference to the annotated type. The sort of this type
+ * reference must be {@link TypeReference#LOCAL_VARIABLE
+ * LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE
+ * RESOURCE_VARIABLE}. See {@link TypeReference}.
+ * @param typePath
+ * the path to the annotated type argument, wildcard bound, array
+ * element type, or static inner type within 'typeRef'. May be
+ * <tt>null</tt> if the annotation targets 'typeRef' as a whole.
+ * @param start
+ * the fist instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (inclusive).
+ * @param end
+ * the last instructions corresponding to the continuous ranges
+ * that make the scope of this local variable (exclusive). This
+ * array must have the same size as the 'start' array.
+ * @param index
+ * the local variable's index in each range. This array must have
+ * the same size as the 'start' array.
+ * @param desc
+ * the class descriptor of the annotation class.
+ * @param visible
+ * <tt>true</tt> if the annotation is visible at runtime.
+ * @return a visitor to visit the annotation values, or <tt>null</tt> if
+ * this visitor is not interested in visiting this annotation.
+ */
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (api < Opcodes.ASM5) {
+ throw new RuntimeException();
+ }
+ if (mv != null) {
+ return mv.visitLocalVariableAnnotation(typeRef, typePath, start,
+ end, index, desc, visible);
+ }
+ return null;
+ }
+
+ /**
+ * Visits a line number declaration.
+ *
+ * @param line
+ * a line number. This number refers to the source file from
+ * which the class was compiled.
+ * @param start
+ * the first instruction corresponding to this line number.
+ * @throws IllegalArgumentException
+ * if <tt>start</tt> has not already been visited by this
+ * visitor (by the {@link #visitLabel visitLabel} method).
+ */
+ public void visitLineNumber(int line, Label start) {
+ if (mv != null) {
+ mv.visitLineNumber(line, start);
+ }
+ }
+
+ /**
+ * Visits the maximum stack size and the maximum number of local variables
+ * of the method.
+ *
+ * @param maxStack
+ * maximum stack size of the method.
+ * @param maxLocals
+ * maximum number of local variables for the method.
+ */
+ public void visitMaxs(int maxStack, int maxLocals) {
+ if (mv != null) {
+ mv.visitMaxs(maxStack, maxLocals);
+ }
+ }
+
+ /**
+ * Visits the end of the method. This method, which is the last one to be
+ * called, is used to inform the visitor that all the annotations and
+ * attributes of the method have been visited.
+ */
+ public void visitEnd() {
+ if (mv != null) {
+ mv.visitEnd();
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodWriter.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodWriter.java
new file mode 100644
index 0000000..778d362
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/MethodWriter.java
@@ -0,0 +1,2915 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * A {@link MethodVisitor} that generates methods in bytecode form. Each visit
+ * method of this class appends the bytecode corresponding to the visited
+ * instruction to a byte vector, in the order these methods are called.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+class MethodWriter extends MethodVisitor {
+
+ /**
+ * Pseudo access flag used to denote constructors.
+ */
+ static final int ACC_CONSTRUCTOR = 0x80000;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero.
+ */
+ static final int SAME_FRAME = 0; // to 63 (0-3f)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)
+
+ /**
+ * Reserved for future use
+ */
+ static final int RESERVED = 128;
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is 1. Offset is bigger then 63;
+ */
+ static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that the k last locals are absent. The value of k is given
+ * by the formula 251-frame_type.
+ */
+ static final int CHOP_FRAME = 248; // to 250 (f8-fA)
+
+ /**
+ * Frame has exactly the same locals as the previous stack map frame and
+ * number of stack items is zero. Offset is bigger then 63;
+ */
+ static final int SAME_FRAME_EXTENDED = 251; // fb
+
+ /**
+ * Frame where current locals are the same as the locals in the previous
+ * frame, except that k additional locals are defined. The value of k is
+ * given by the formula frame_type-251.
+ */
+ static final int APPEND_FRAME = 252; // to 254 // fc-fe
+
+ /**
+ * Full frame
+ */
+ static final int FULL_FRAME = 255; // ff
+
+ /**
+ * Indicates that the stack map frames must be recomputed from scratch. In
+ * this case the maximum stack size and number of local variables is also
+ * recomputed from scratch.
+ *
+ * @see #compute
+ */
+ private static final int FRAMES = 0;
+
+ /**
+ * Indicates that the maximum stack size and number of local variables must
+ * be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int MAXS = 1;
+
+ /**
+ * Indicates that nothing must be automatically computed.
+ *
+ * @see #compute
+ */
+ private static final int NOTHING = 2;
+
+ /**
+ * The class writer to which this method must be added.
+ */
+ final ClassWriter cw;
+
+ /**
+ * Access flags of this method.
+ */
+ private int access;
+
+ /**
+ * The index of the constant pool item that contains the name of this
+ * method.
+ */
+ private final int name;
+
+ /**
+ * The index of the constant pool item that contains the descriptor of this
+ * method.
+ */
+ private final int desc;
+
+ /**
+ * The descriptor of this method.
+ */
+ private final String descriptor;
+
+ /**
+ * The signature of this method.
+ */
+ String signature;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the index of the first byte to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderOffset;
+
+ /**
+ * If not zero, indicates that the code of this method must be copied from
+ * the ClassReader associated to this writer in <code>cw.cr</code>. More
+ * precisely, this field gives the number of bytes to copied from
+ * <code>cw.cr.b</code>.
+ */
+ int classReaderLength;
+
+ /**
+ * Number of exceptions that can be thrown by this method.
+ */
+ int exceptionCount;
+
+ /**
+ * The exceptions that can be thrown by this method. More precisely, this
+ * array contains the indexes of the constant pool items that contain the
+ * internal names of these exception classes.
+ */
+ int[] exceptions;
+
+ /**
+ * The annotation default attribute of this method. May be <tt>null</tt>.
+ */
+ private ByteVector annd;
+
+ /**
+ * The runtime visible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter anns;
+
+ /**
+ * The runtime invisible annotations of this method. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ianns;
+
+ /**
+ * The runtime visible type annotations of this method. May be <tt>null</tt>
+ * .
+ */
+ private AnnotationWriter tanns;
+
+ /**
+ * The runtime invisible type annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter itanns;
+
+ /**
+ * The runtime visible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] panns;
+
+ /**
+ * The runtime invisible parameter annotations of this method. May be
+ * <tt>null</tt>.
+ */
+ private AnnotationWriter[] ipanns;
+
+ /**
+ * The number of synthetic parameters of this method.
+ */
+ private int synthetics;
+
+ /**
+ * The non standard attributes of the method.
+ */
+ private Attribute attrs;
+
+ /**
+ * The bytecode of this method.
+ */
+ private ByteVector code = new ByteVector();
+
+ /**
+ * Maximum stack size of this method.
+ */
+ private int maxStack;
+
+ /**
+ * Maximum number of local variables for this method.
+ */
+ private int maxLocals;
+
+ /**
+ * Number of local variables in the current stack map frame.
+ */
+ private int currentLocals;
+
+ /**
+ * Number of stack map frames in the StackMapTable attribute.
+ */
+ private int frameCount;
+
+ /**
+ * The StackMapTable attribute.
+ */
+ private ByteVector stackMap;
+
+ /**
+ * The offset of the last frame that was written in the StackMapTable
+ * attribute.
+ */
+ private int previousFrameOffset;
+
+ /**
+ * The last frame that was written in the StackMapTable attribute.
+ *
+ * @see #frame
+ */
+ private int[] previousFrame;
+
+ /**
+ * The current stack map frame. The first element contains the offset of the
+ * instruction to which the frame corresponds, the second element is the
+ * number of locals and the third one is the number of stack elements. The
+ * local variables start at index 3 and are followed by the operand stack
+ * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =
+ * nStack, frame[3] = nLocal. All types are encoded as integers, with the
+ * same format as the one used in {@link Label}, but limited to BASE types.
+ */
+ private int[] frame;
+
+ /**
+ * Number of elements in the exception handler list.
+ */
+ private int handlerCount;
+
+ /**
+ * The first element in the exception handler list.
+ */
+ private Handler firstHandler;
+
+ /**
+ * The last element in the exception handler list.
+ */
+ private Handler lastHandler;
+
+ /**
+ * Number of entries in the MethodParameters attribute.
+ */
+ private int methodParametersCount;
+
+ /**
+ * The MethodParameters attribute.
+ */
+ private ByteVector methodParameters;
+
+ /**
+ * Number of entries in the LocalVariableTable attribute.
+ */
+ private int localVarCount;
+
+ /**
+ * The LocalVariableTable attribute.
+ */
+ private ByteVector localVar;
+
+ /**
+ * Number of entries in the LocalVariableTypeTable attribute.
+ */
+ private int localVarTypeCount;
+
+ /**
+ * The LocalVariableTypeTable attribute.
+ */
+ private ByteVector localVarType;
+
+ /**
+ * Number of entries in the LineNumberTable attribute.
+ */
+ private int lineNumberCount;
+
+ /**
+ * The LineNumberTable attribute.
+ */
+ private ByteVector lineNumber;
+
+ /**
+ * The start offset of the last visited instruction.
+ */
+ private int lastCodeOffset;
+
+ /**
+ * The runtime visible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ctanns;
+
+ /**
+ * The runtime invisible type annotations of the code. May be <tt>null</tt>.
+ */
+ private AnnotationWriter ictanns;
+
+ /**
+ * The non standard attributes of the method's code.
+ */
+ private Attribute cattrs;
+
+ /**
+ * Indicates if some jump instructions are too small and need to be resized.
+ */
+ private boolean resize;
+
+ /**
+ * The number of subroutines in this method.
+ */
+ private int subroutines;
+
+ // ------------------------------------------------------------------------
+
+ /*
+ * Fields for the control flow graph analysis algorithm (used to compute the
+ * maximum stack size). A control flow graph contains one node per "basic
+ * block", and one edge per "jump" from one basic block to another. Each
+ * node (i.e., each basic block) is represented by the Label object that
+ * corresponds to the first instruction of this basic block. Each node also
+ * stores the list of its successors in the graph, as a linked list of Edge
+ * objects.
+ */
+
+ /**
+ * Indicates what must be automatically computed.
+ *
+ * @see #FRAMES
+ * @see #MAXS
+ * @see #NOTHING
+ */
+ private final int compute;
+
+ /**
+ * A list of labels. This list is the list of basic blocks in the method,
+ * i.e. a list of Label objects linked to each other by their
+ * {@link Label#successor} field, in the order they are visited by
+ * {@link MethodVisitor#visitLabel}, and starting with the first basic
+ * block.
+ */
+ private Label labels;
+
+ /**
+ * The previous basic block.
+ */
+ private Label previousBlock;
+
+ /**
+ * The current basic block.
+ */
+ private Label currentBlock;
+
+ /**
+ * The (relative) stack size after the last visited instruction. This size
+ * is relative to the beginning of the current basic block, i.e., the true
+ * stack size after the last visited instruction is equal to the
+ * {@link Label#inputStackTop beginStackSize} of the current basic block
+ * plus <tt>stackSize</tt>.
+ */
+ private int stackSize;
+
+ /**
+ * The (relative) maximum stack size after the last visited instruction.
+ * This size is relative to the beginning of the current basic block, i.e.,
+ * the true maximum stack size after the last visited instruction is equal
+ * to the {@link Label#inputStackTop beginStackSize} of the current basic
+ * block plus <tt>stackSize</tt>.
+ */
+ private int maxStackSize;
+
+ // ------------------------------------------------------------------------
+ // Constructor
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a new {@link MethodWriter}.
+ *
+ * @param cw
+ * the class writer in which the method must be added.
+ * @param access
+ * the method's access flags (see {@link Opcodes}).
+ * @param name
+ * the method's name.
+ * @param desc
+ * the method's descriptor (see {@link Type}).
+ * @param signature
+ * the method's signature. May be <tt>null</tt>.
+ * @param exceptions
+ * the internal names of the method's exceptions. May be
+ * <tt>null</tt>.
+ * @param computeMaxs
+ * <tt>true</tt> if the maximum stack size and number of local
+ * variables must be automatically computed.
+ * @param computeFrames
+ * <tt>true</tt> if the stack map tables must be recomputed from
+ * scratch.
+ */
+ MethodWriter(final ClassWriter cw, final int access, final String name,
+ final String desc, final String signature,
+ final String[] exceptions, final boolean computeMaxs,
+ final boolean computeFrames) {
+ super(Opcodes.ASM5);
+ if (cw.firstMethod == null) {
+ cw.firstMethod = this;
+ } else {
+ cw.lastMethod.mv = this;
+ }
+ cw.lastMethod = this;
+ this.cw = cw;
+ this.access = access;
+ if ("<init>".equals(name)) {
+ this.access |= ACC_CONSTRUCTOR;
+ }
+ this.name = cw.newUTF8(name);
+ this.desc = cw.newUTF8(desc);
+ this.descriptor = desc;
+ if (ClassReader.SIGNATURES) {
+ this.signature = signature;
+ }
+ if (exceptions != null && exceptions.length > 0) {
+ exceptionCount = exceptions.length;
+ this.exceptions = new int[exceptionCount];
+ for (int i = 0; i < exceptionCount; ++i) {
+ this.exceptions[i] = cw.newClass(exceptions[i]);
+ }
+ }
+ this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);
+ if (computeMaxs || computeFrames) {
+ // updates maxLocals
+ int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;
+ if ((access & Opcodes.ACC_STATIC) != 0) {
+ --size;
+ }
+ maxLocals = size;
+ currentLocals = size;
+ // creates and visits the label for the first basic block
+ labels = new Label();
+ labels.status |= Label.PUSHED;
+ visitLabel(labels);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Implementation of the MethodVisitor abstract class
+ // ------------------------------------------------------------------------
+
+ @Override
+ public void visitParameter(String name, int access) {
+ if (methodParameters == null) {
+ methodParameters = new ByteVector();
+ }
+ ++methodParametersCount;
+ methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))
+ .putShort(access);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotationDefault() {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ annd = new ByteVector();
+ return new AnnotationWriter(cw, false, annd, null, 0);
+ }
+
+ @Override
+ public AnnotationVisitor visitAnnotation(final String desc,
+ final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ aw.next = anns;
+ anns = aw;
+ } else {
+ aw.next = ianns;
+ ianns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitTypeAnnotation(final int typeRef,
+ final TypePath typePath, final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = tanns;
+ tanns = aw;
+ } else {
+ aw.next = itanns;
+ itanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public AnnotationVisitor visitParameterAnnotation(final int parameter,
+ final String desc, final boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ if ("Ljava/lang/Synthetic;".equals(desc)) {
+ // workaround for a bug in javac with synthetic parameters
+ // see ClassReader.readParameterAnnotations
+ synthetics = Math.max(synthetics, parameter + 1);
+ return new AnnotationWriter(cw, false, bv, null, 0);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);
+ if (visible) {
+ if (panns == null) {
+ panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = panns[parameter];
+ panns[parameter] = aw;
+ } else {
+ if (ipanns == null) {
+ ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];
+ }
+ aw.next = ipanns[parameter];
+ ipanns[parameter] = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitAttribute(final Attribute attr) {
+ if (attr.isCodeAttribute()) {
+ attr.next = cattrs;
+ cattrs = attr;
+ } else {
+ attr.next = attrs;
+ attrs = attr;
+ }
+ }
+
+ @Override
+ public void visitCode() {
+ }
+
+ @Override
+ public void visitFrame(final int type, final int nLocal,
+ final Object[] local, final int nStack, final Object[] stack) {
+ if (!ClassReader.FRAMES || compute == FRAMES) {
+ return;
+ }
+
+ if (type == Opcodes.F_NEW) {
+ if (previousFrame == null) {
+ visitImplicitFirstFrame();
+ }
+ currentLocals = nLocal;
+ int frameIndex = startFrame(code.length, nLocal, nStack);
+ for (int i = 0; i < nLocal; ++i) {
+ if (local[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) local[i]);
+ } else if (local[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) local[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) local[i]).position);
+ }
+ }
+ for (int i = 0; i < nStack; ++i) {
+ if (stack[i] instanceof String) {
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType((String) stack[i]);
+ } else if (stack[i] instanceof Integer) {
+ frame[frameIndex++] = ((Integer) stack[i]).intValue();
+ } else {
+ frame[frameIndex++] = Frame.UNINITIALIZED
+ | cw.addUninitializedType("",
+ ((Label) stack[i]).position);
+ }
+ }
+ endFrame();
+ } else {
+ int delta;
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ delta = code.length;
+ } else {
+ delta = code.length - previousFrameOffset - 1;
+ if (delta < 0) {
+ if (type == Opcodes.F_SAME) {
+ return;
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ }
+
+ switch (type) {
+ case Opcodes.F_FULL:
+ currentLocals = nLocal;
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ stackMap.putShort(nStack);
+ for (int i = 0; i < nStack; ++i) {
+ writeFrameType(stack[i]);
+ }
+ break;
+ case Opcodes.F_APPEND:
+ currentLocals += nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);
+ for (int i = 0; i < nLocal; ++i) {
+ writeFrameType(local[i]);
+ }
+ break;
+ case Opcodes.F_CHOP:
+ currentLocals -= nLocal;
+ stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);
+ break;
+ case Opcodes.F_SAME:
+ if (delta < 64) {
+ stackMap.putByte(delta);
+ } else {
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ }
+ break;
+ case Opcodes.F_SAME1:
+ if (delta < 64) {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ } else {
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)
+ .putShort(delta);
+ }
+ writeFrameType(stack[0]);
+ break;
+ }
+
+ previousFrameOffset = code.length;
+ ++frameCount;
+ }
+
+ maxStack = Math.max(maxStack, nStack);
+ maxLocals = Math.max(maxLocals, currentLocals);
+ }
+
+ @Override
+ public void visitInsn(final int opcode) {
+ lastCodeOffset = code.length;
+ // adds the instruction to the bytecode of the method
+ code.putByte(opcode);
+ // update currentBlock
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ } else {
+ // updates current and max stack sizes
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ // if opcode == ATHROW or xRETURN, ends current block (no successor)
+ if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)
+ || opcode == Opcodes.ATHROW) {
+ noSuccessor();
+ }
+ }
+ }
+
+ @Override
+ public void visitIntInsn(final int opcode, final int operand) {
+ lastCodeOffset = code.length;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, operand, null, null);
+ } else if (opcode != Opcodes.NEWARRAY) {
+ // updates current and max stack sizes only for NEWARRAY
+ // (stack size variation = 0 for BIPUSH or SIPUSH)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (opcode == Opcodes.SIPUSH) {
+ code.put12(opcode, operand);
+ } else { // BIPUSH or NEWARRAY
+ code.put11(opcode, operand);
+ }
+ }
+
+ @Override
+ public void visitVarInsn(final int opcode, final int var) {
+ lastCodeOffset = code.length;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, var, null, null);
+ } else {
+ // updates current and max stack sizes
+ if (opcode == Opcodes.RET) {
+ // no stack change, but end of current block (no successor)
+ currentBlock.status |= Label.RET;
+ // save 'stackSize' here for future use
+ // (see {@link #findSubroutineSuccessors})
+ currentBlock.inputStackTop = stackSize;
+ noSuccessor();
+ } else { // xLOAD or xSTORE
+ int size = stackSize + Frame.SIZE[opcode];
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n;
+ if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD
+ || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {
+ n = var + 2;
+ } else {
+ n = var + 1;
+ }
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (var < 4 && opcode != Opcodes.RET) {
+ int opt;
+ if (opcode < Opcodes.ISTORE) {
+ /* ILOAD_0 */
+ opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;
+ } else {
+ /* ISTORE_0 */
+ opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;
+ }
+ code.putByte(opt);
+ } else if (var >= 256) {
+ code.putByte(196 /* WIDE */).put12(opcode, var);
+ } else {
+ code.put11(opcode, var);
+ }
+ if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {
+ visitLabel(new Label());
+ }
+ }
+
+ @Override
+ public void visitTypeInsn(final int opcode, final String type) {
+ lastCodeOffset = code.length;
+ Item i = cw.newClassItem(type);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, code.length, cw, i);
+ } else if (opcode == Opcodes.NEW) {
+ // updates current and max stack sizes only if opcode == NEW
+ // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)
+ int size = stackSize + 1;
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ @Override
+ public void visitFieldInsn(final int opcode, final String owner,
+ final String name, final String desc) {
+ lastCodeOffset = code.length;
+ Item i = cw.newFieldItem(owner, name, desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ char c = desc.charAt(0);
+ switch (opcode) {
+ case Opcodes.GETSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);
+ break;
+ case Opcodes.PUTSTATIC:
+ size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);
+ break;
+ case Opcodes.GETFIELD:
+ size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);
+ break;
+ // case Constants.PUTFIELD:
+ default:
+ size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);
+ break;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(opcode, i.index);
+ }
+
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner,
+ final String name, final String desc, final boolean itf) {
+ lastCodeOffset = code.length;
+ Item i = cw.newMethodItem(owner, name, desc, itf);
+ int argSize = i.intVal;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, cw, i);
+ } else {
+ /*
+ * computes the stack size variation. In order not to recompute
+ * several times this variation for the same Item, we use the
+ * intVal field of this item to store this variation, once it
+ * has been computed. More precisely this intVal field stores
+ * the sizes of the arguments and of the return value
+ * corresponding to desc.
+ */
+ if (argSize == 0) {
+ // the above sizes have not been computed yet,
+ // so we compute them...
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ // ... and we save them in order
+ // not to recompute them in the future
+ i.intVal = argSize;
+ }
+ int size;
+ if (opcode == Opcodes.INVOKESTATIC) {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+ } else {
+ size = stackSize - (argSize >> 2) + (argSize & 0x03);
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if (opcode == Opcodes.INVOKEINTERFACE) {
+ if (argSize == 0) {
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ i.intVal = argSize;
+ }
+ code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);
+ } else {
+ code.put12(opcode, i.index);
+ }
+ }
+
+ @Override
+ public void visitInvokeDynamicInsn(final String name, final String desc,
+ final Handle bsm, final Object... bsmArgs) {
+ lastCodeOffset = code.length;
+ Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);
+ int argSize = i.intVal;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);
+ } else {
+ /*
+ * computes the stack size variation. In order not to recompute
+ * several times this variation for the same Item, we use the
+ * intVal field of this item to store this variation, once it
+ * has been computed. More precisely this intVal field stores
+ * the sizes of the arguments and of the return value
+ * corresponding to desc.
+ */
+ if (argSize == 0) {
+ // the above sizes have not been computed yet,
+ // so we compute them...
+ argSize = Type.getArgumentsAndReturnSizes(desc);
+ // ... and we save them in order
+ // not to recompute them in the future
+ i.intVal = argSize;
+ }
+ int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;
+
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(Opcodes.INVOKEDYNAMIC, i.index);
+ code.putShort(0);
+ }
+
+ @Override
+ public void visitJumpInsn(final int opcode, final Label label) {
+ lastCodeOffset = code.length;
+ Label nextInsn = null;
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(opcode, 0, null, null);
+ // 'label' is the target of a jump instruction
+ label.getFirst().status |= Label.TARGET;
+ // adds 'label' as a successor of this basic block
+ addSuccessor(Edge.NORMAL, label);
+ if (opcode != Opcodes.GOTO) {
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ }
+ } else {
+ if (opcode == Opcodes.JSR) {
+ if ((label.status & Label.SUBROUTINE) == 0) {
+ label.status |= Label.SUBROUTINE;
+ ++subroutines;
+ }
+ currentBlock.status |= Label.JSR;
+ addSuccessor(stackSize + 1, label);
+ // creates a Label for the next basic block
+ nextInsn = new Label();
+ /*
+ * note that, by construction in this method, a JSR block
+ * has at least two successors in the control flow graph:
+ * the first one leads the next instruction after the JSR,
+ * while the second one leads to the JSR target.
+ */
+ } else {
+ // updates current stack size (max stack size unchanged
+ // because stack size variation always negative in this
+ // case)
+ stackSize += Frame.SIZE[opcode];
+ addSuccessor(stackSize, label);
+ }
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((label.status & Label.RESOLVED) != 0
+ && label.position - code.length < Short.MIN_VALUE) {
+ /*
+ * case of a backward jump with an offset < -32768. In this case we
+ * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the
+ * "opposite" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>
+ * designates the instruction just after the GOTO_W.
+ */
+ if (opcode == Opcodes.GOTO) {
+ code.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ code.putByte(201); // JSR_W
+ } else {
+ // if the IF instruction is transformed into IFNOT GOTO_W the
+ // next instruction becomes the target of the IFNOT instruction
+ if (nextInsn != null) {
+ nextInsn.status |= Label.TARGET;
+ }
+ code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ code.putShort(8); // jump offset
+ code.putByte(200); // GOTO_W
+ }
+ label.put(this, code, code.length - 1, true);
+ } else {
+ /*
+ * case of a backward jump with an offset >= -32768, or of a forward
+ * jump with, of course, an unknown offset. In these cases we store
+ * the offset in 2 bytes (which will be increased in
+ * resizeInstructions, if needed).
+ */
+ code.putByte(opcode);
+ label.put(this, code, code.length - 1, false);
+ }
+ if (currentBlock != null) {
+ if (nextInsn != null) {
+ // if the jump instruction is not a GOTO, the next instruction
+ // is also a successor of this instruction. Calling visitLabel
+ // adds the label of this next instruction as a successor of the
+ // current block, and starts a new basic block
+ visitLabel(nextInsn);
+ }
+ if (opcode == Opcodes.GOTO) {
+ noSuccessor();
+ }
+ }
+ }
+
+ @Override
+ public void visitLabel(final Label label) {
+ // resolves previous forward references to label, if any
+ resize |= label.resolve(this, code.length, code.data);
+ // updates currentBlock
+ if ((label.status & Label.DEBUG) != 0) {
+ return;
+ }
+ if (compute == FRAMES) {
+ if (currentBlock != null) {
+ if (label.position == currentBlock.position) {
+ // successive labels, do not start a new basic block
+ currentBlock.status |= (label.status & Label.TARGET);
+ label.frame = currentBlock.frame;
+ return;
+ }
+ // ends current block (with one new successor)
+ addSuccessor(Edge.NORMAL, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ if (label.frame == null) {
+ label.frame = new Frame();
+ label.frame.owner = label;
+ }
+ // updates the basic block list
+ if (previousBlock != null) {
+ if (label.position == previousBlock.position) {
+ previousBlock.status |= (label.status & Label.TARGET);
+ label.frame = previousBlock.frame;
+ currentBlock = previousBlock;
+ return;
+ }
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ } else if (compute == MAXS) {
+ if (currentBlock != null) {
+ // ends current block (with one new successor)
+ currentBlock.outputStackMax = maxStackSize;
+ addSuccessor(stackSize, label);
+ }
+ // begins a new current block
+ currentBlock = label;
+ // resets the relative current and max stack sizes
+ stackSize = 0;
+ maxStackSize = 0;
+ // updates the basic block list
+ if (previousBlock != null) {
+ previousBlock.successor = label;
+ }
+ previousBlock = label;
+ }
+ }
+
+ @Override
+ public void visitLdcInsn(final Object cst) {
+ lastCodeOffset = code.length;
+ Item i = cw.newConstItem(cst);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);
+ } else {
+ int size;
+ // computes the stack size variation
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
+ size = stackSize + 2;
+ } else {
+ size = stackSize + 1;
+ }
+ // updates current and max stack sizes
+ if (size > maxStackSize) {
+ maxStackSize = size;
+ }
+ stackSize = size;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ int index = i.index;
+ if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {
+ code.put12(20 /* LDC2_W */, index);
+ } else if (index >= 256) {
+ code.put12(19 /* LDC_W */, index);
+ } else {
+ code.put11(Opcodes.LDC, index);
+ }
+ }
+
+ @Override
+ public void visitIincInsn(final int var, final int increment) {
+ lastCodeOffset = code.length;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.IINC, var, null, null);
+ }
+ }
+ if (compute != NOTHING) {
+ // updates max locals
+ int n = var + 1;
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ if ((var > 255) || (increment > 127) || (increment < -128)) {
+ code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)
+ .putShort(increment);
+ } else {
+ code.putByte(Opcodes.IINC).put11(var, increment);
+ }
+ }
+
+ @Override
+ public void visitTableSwitchInsn(final int min, final int max,
+ final Label dflt, final Label... labels) {
+ lastCodeOffset = code.length;
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.TABLESWITCH);
+ code.putByteArray(null, 0, (4 - code.length % 4) % 4);
+ dflt.put(this, code, source, true);
+ code.putInt(min).putInt(max);
+ for (int i = 0; i < labels.length; ++i) {
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ @Override
+ public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
+ final Label[] labels) {
+ lastCodeOffset = code.length;
+ // adds the instruction to the bytecode of the method
+ int source = code.length;
+ code.putByte(Opcodes.LOOKUPSWITCH);
+ code.putByteArray(null, 0, (4 - code.length % 4) % 4);
+ dflt.put(this, code, source, true);
+ code.putInt(labels.length);
+ for (int i = 0; i < labels.length; ++i) {
+ code.putInt(keys[i]);
+ labels[i].put(this, code, source, true);
+ }
+ // updates currentBlock
+ visitSwitchInsn(dflt, labels);
+ }
+
+ private void visitSwitchInsn(final Label dflt, final Label[] labels) {
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);
+ // adds current block successors
+ addSuccessor(Edge.NORMAL, dflt);
+ dflt.getFirst().status |= Label.TARGET;
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(Edge.NORMAL, labels[i]);
+ labels[i].getFirst().status |= Label.TARGET;
+ }
+ } else {
+ // updates current stack size (max stack size unchanged)
+ --stackSize;
+ // adds current block successors
+ addSuccessor(stackSize, dflt);
+ for (int i = 0; i < labels.length; ++i) {
+ addSuccessor(stackSize, labels[i]);
+ }
+ }
+ // ends current block
+ noSuccessor();
+ }
+ }
+
+ @Override
+ public void visitMultiANewArrayInsn(final String desc, final int dims) {
+ lastCodeOffset = code.length;
+ Item i = cw.newClassItem(desc);
+ // Label currentBlock = this.currentBlock;
+ if (currentBlock != null) {
+ if (compute == FRAMES) {
+ currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);
+ } else {
+ // updates current stack size (max stack size unchanged because
+ // stack size variation always negative or null)
+ stackSize += 1 - dims;
+ }
+ }
+ // adds the instruction to the bytecode of the method
+ code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);
+ }
+
+ @Override
+ public AnnotationVisitor visitInsnAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitTryCatchBlock(final Label start, final Label end,
+ final Label handler, final String type) {
+ ++handlerCount;
+ Handler h = new Handler();
+ h.start = start;
+ h.end = end;
+ h.handler = handler;
+ h.desc = type;
+ h.type = type != null ? cw.newClass(type) : 0;
+ if (lastHandler == null) {
+ firstHandler = h;
+ } else {
+ lastHandler.next = h;
+ }
+ lastHandler = h;
+ }
+
+ @Override
+ public AnnotationVisitor visitTryCatchAnnotation(int typeRef,
+ TypePath typePath, String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ AnnotationWriter.putTarget(typeRef, typePath, bv);
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitLocalVariable(final String name, final String desc,
+ final String signature, final Label start, final Label end,
+ final int index) {
+ if (signature != null) {
+ if (localVarType == null) {
+ localVarType = new ByteVector();
+ }
+ ++localVarTypeCount;
+ localVarType.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))
+ .putShort(index);
+ }
+ if (localVar == null) {
+ localVar = new ByteVector();
+ }
+ ++localVarCount;
+ localVar.putShort(start.position)
+ .putShort(end.position - start.position)
+ .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))
+ .putShort(index);
+ if (compute != NOTHING) {
+ // updates max locals
+ char c = desc.charAt(0);
+ int n = index + (c == 'J' || c == 'D' ? 2 : 1);
+ if (n > maxLocals) {
+ maxLocals = n;
+ }
+ }
+ }
+
+ @Override
+ public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,
+ TypePath typePath, Label[] start, Label[] end, int[] index,
+ String desc, boolean visible) {
+ if (!ClassReader.ANNOTATIONS) {
+ return null;
+ }
+ ByteVector bv = new ByteVector();
+ // write target_type and target_info
+ bv.putByte(typeRef >>> 24).putShort(start.length);
+ for (int i = 0; i < start.length; ++i) {
+ bv.putShort(start[i].position)
+ .putShort(end[i].position - start[i].position)
+ .putShort(index[i]);
+ }
+ if (typePath == null) {
+ bv.putByte(0);
+ } else {
+ int length = typePath.b[typePath.offset] * 2 + 1;
+ bv.putByteArray(typePath.b, typePath.offset, length);
+ }
+ // write type, and reserve space for values count
+ bv.putShort(cw.newUTF8(desc)).putShort(0);
+ AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,
+ bv.length - 2);
+ if (visible) {
+ aw.next = ctanns;
+ ctanns = aw;
+ } else {
+ aw.next = ictanns;
+ ictanns = aw;
+ }
+ return aw;
+ }
+
+ @Override
+ public void visitLineNumber(final int line, final Label start) {
+ if (lineNumber == null) {
+ lineNumber = new ByteVector();
+ }
+ ++lineNumberCount;
+ lineNumber.putShort(start.position);
+ lineNumber.putShort(line);
+ }
+
+ @Override
+ public void visitMaxs(final int maxStack, final int maxLocals) {
+ if (resize) {
+ // replaces the temporary jump opcodes introduced by Label.resolve.
+ if (ClassReader.RESIZE) {
+ resizeInstructions();
+ } else {
+ throw new RuntimeException("Method code too large!");
+ }
+ }
+ if (ClassReader.FRAMES && compute == FRAMES) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start.getFirst();
+ Label h = handler.handler.getFirst();
+ Label e = handler.end.getFirst();
+ // computes the kind of the edges to 'h'
+ String t = handler.desc == null ? "java/lang/Throwable"
+ : handler.desc;
+ int kind = Frame.OBJECT | cw.addType(t);
+ // h is an exception handler
+ h.status |= Label.TARGET;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = kind;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ b.next = l.successors;
+ l.successors = b;
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ // creates and visits the first (implicit) frame
+ Frame f = labels.frame;
+ Type[] args = Type.getArgumentTypes(descriptor);
+ f.initInputFrame(cw, access, args, this.maxLocals);
+ visitFrame(f);
+
+ /*
+ * fix point algorithm: mark the first basic block as 'changed'
+ * (i.e. put it in the 'changed' list) and, while there are changed
+ * basic blocks, choose one, mark it as unchanged, and update its
+ * successors (which can be changed in the process).
+ */
+ int max = 0;
+ Label changed = labels;
+ while (changed != null) {
+ // removes a basic block from the list of changed basic blocks
+ Label l = changed;
+ changed = changed.next;
+ l.next = null;
+ f = l.frame;
+ // a reachable jump target must be stored in the stack map
+ if ((l.status & Label.TARGET) != 0) {
+ l.status |= Label.STORE;
+ }
+ // all visited labels are reachable, by definition
+ l.status |= Label.REACHABLE;
+ // updates the (absolute) maximum stack size
+ int blockMax = f.inputStack.length + l.outputStackMax;
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // updates the successors of the current basic block
+ Edge e = l.successors;
+ while (e != null) {
+ Label n = e.successor.getFirst();
+ boolean change = f.merge(cw, n.frame, e.info);
+ if (change && n.next == null) {
+ // if n has changed and is not already in the 'changed'
+ // list, adds it to this list
+ n.next = changed;
+ changed = n;
+ }
+ e = e.next;
+ }
+ }
+
+ // visits all the frames that must be stored in the stack map
+ Label l = labels;
+ while (l != null) {
+ f = l.frame;
+ if ((l.status & Label.STORE) != 0) {
+ visitFrame(f);
+ }
+ if ((l.status & Label.REACHABLE) == 0) {
+ // finds start and end of dead basic block
+ Label k = l.successor;
+ int start = l.position;
+ int end = (k == null ? code.length : k.position) - 1;
+ // if non empty basic block
+ if (end >= start) {
+ max = Math.max(max, 1);
+ // replaces instructions with NOP ... NOP ATHROW
+ for (int i = start; i < end; ++i) {
+ code.data[i] = Opcodes.NOP;
+ }
+ code.data[end] = (byte) Opcodes.ATHROW;
+ // emits a frame for this unreachable block
+ int frameIndex = startFrame(start, 0, 1);
+ frame[frameIndex] = Frame.OBJECT
+ | cw.addType("java/lang/Throwable");
+ endFrame();
+ // removes the start-end range from the exception
+ // handlers
+ firstHandler = Handler.remove(firstHandler, l, k);
+ }
+ }
+ l = l.successor;
+ }
+
+ handler = firstHandler;
+ handlerCount = 0;
+ while (handler != null) {
+ handlerCount += 1;
+ handler = handler.next;
+ }
+
+ this.maxStack = max;
+ } else if (compute == MAXS) {
+ // completes the control flow graph with exception handler blocks
+ Handler handler = firstHandler;
+ while (handler != null) {
+ Label l = handler.start;
+ Label h = handler.handler;
+ Label e = handler.end;
+ // adds 'h' as a successor of labels between 'start' and 'end'
+ while (l != e) {
+ // creates an edge to 'h'
+ Edge b = new Edge();
+ b.info = Edge.EXCEPTION;
+ b.successor = h;
+ // adds it to the successors of 'l'
+ if ((l.status & Label.JSR) == 0) {
+ b.next = l.successors;
+ l.successors = b;
+ } else {
+ // if l is a JSR block, adds b after the first two edges
+ // to preserve the hypothesis about JSR block successors
+ // order (see {@link #visitJumpInsn})
+ b.next = l.successors.next.next;
+ l.successors.next.next = b;
+ }
+ // goes to the next label
+ l = l.successor;
+ }
+ handler = handler.next;
+ }
+
+ if (subroutines > 0) {
+ // completes the control flow graph with the RET successors
+ /*
+ * first step: finds the subroutines. This step determines, for
+ * each basic block, to which subroutine(s) it belongs.
+ */
+ // finds the basic blocks that belong to the "main" subroutine
+ int id = 0;
+ labels.visitSubroutine(null, 1, subroutines);
+ // finds the basic blocks that belong to the real subroutines
+ Label l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ // if this subroutine has not been visited yet...
+ if ((subroutine.status & Label.VISITED) == 0) {
+ // ...assigns it a new id and finds its basic blocks
+ id += 1;
+ subroutine.visitSubroutine(null, (id / 32L) << 32
+ | (1L << (id % 32)), subroutines);
+ }
+ }
+ l = l.successor;
+ }
+ // second step: finds the successors of RET blocks
+ l = labels;
+ while (l != null) {
+ if ((l.status & Label.JSR) != 0) {
+ Label L = labels;
+ while (L != null) {
+ L.status &= ~Label.VISITED2;
+ L = L.successor;
+ }
+ // the subroutine is defined by l's TARGET, not by l
+ Label subroutine = l.successors.next.successor;
+ subroutine.visitSubroutine(l, 0, subroutines);
+ }
+ l = l.successor;
+ }
+ }
+
+ /*
+ * control flow analysis algorithm: while the block stack is not
+ * empty, pop a block from this stack, update the max stack size,
+ * compute the true (non relative) begin stack size of the
+ * successors of this block, and push these successors onto the
+ * stack (unless they have already been pushed onto the stack).
+ * Note: by hypothesis, the {@link Label#inputStackTop} of the
+ * blocks in the block stack are the true (non relative) beginning
+ * stack sizes of these blocks.
+ */
+ int max = 0;
+ Label stack = labels;
+ while (stack != null) {
+ // pops a block from the stack
+ Label l = stack;
+ stack = stack.next;
+ // computes the true (non relative) max stack size of this block
+ int start = l.inputStackTop;
+ int blockMax = start + l.outputStackMax;
+ // updates the global max stack size
+ if (blockMax > max) {
+ max = blockMax;
+ }
+ // analyzes the successors of the block
+ Edge b = l.successors;
+ if ((l.status & Label.JSR) != 0) {
+ // ignores the first edge of JSR blocks (virtual successor)
+ b = b.next;
+ }
+ while (b != null) {
+ l = b.successor;
+ // if this successor has not already been pushed...
+ if ((l.status & Label.PUSHED) == 0) {
+ // computes its true beginning stack size...
+ l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start
+ + b.info;
+ // ...and pushes it onto the stack
+ l.status |= Label.PUSHED;
+ l.next = stack;
+ stack = l;
+ }
+ b = b.next;
+ }
+ }
+ this.maxStack = Math.max(maxStack, max);
+ } else {
+ this.maxStack = maxStack;
+ this.maxLocals = maxLocals;
+ }
+ }
+
+ @Override
+ public void visitEnd() {
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: control flow analysis algorithm
+ // ------------------------------------------------------------------------
+
+ /**
+ * Adds a successor to the {@link #currentBlock currentBlock} block.
+ *
+ * @param info
+ * information about the control flow edge to be added.
+ * @param successor
+ * the successor block to be added to the current block.
+ */
+ private void addSuccessor(final int info, final Label successor) {
+ // creates and initializes an Edge object...
+ Edge b = new Edge();
+ b.info = info;
+ b.successor = successor;
+ // ...and adds it to the successor list of the currentBlock block
+ b.next = currentBlock.successors;
+ currentBlock.successors = b;
+ }
+
+ /**
+ * Ends the current basic block. This method must be used in the case where
+ * the current basic block does not have any successor.
+ */
+ private void noSuccessor() {
+ if (compute == FRAMES) {
+ Label l = new Label();
+ l.frame = new Frame();
+ l.frame.owner = l;
+ l.resolve(this, code.length, code.data);
+ previousBlock.successor = l;
+ previousBlock = l;
+ } else {
+ currentBlock.outputStackMax = maxStackSize;
+ }
+ currentBlock = null;
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: stack map frames
+ // ------------------------------------------------------------------------
+
+ /**
+ * Visits a frame that has been computed from scratch.
+ *
+ * @param f
+ * the frame that must be visited.
+ */
+ private void visitFrame(final Frame f) {
+ int i, t;
+ int nTop = 0;
+ int nLocal = 0;
+ int nStack = 0;
+ int[] locals = f.inputLocals;
+ int[] stacks = f.inputStack;
+ // computes the number of locals (ignores TOP types that are just after
+ // a LONG or a DOUBLE, and all trailing TOP types)
+ for (i = 0; i < locals.length; ++i) {
+ t = locals[i];
+ if (t == Frame.TOP) {
+ ++nTop;
+ } else {
+ nLocal += nTop + 1;
+ nTop = 0;
+ }
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // computes the stack size (ignores TOP types that are just after
+ // a LONG or a DOUBLE)
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ ++nStack;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ // visits the frame and its content
+ int frameIndex = startFrame(f.owner.position, nLocal, nStack);
+ for (i = 0; nLocal > 0; ++i, --nLocal) {
+ t = locals[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ for (i = 0; i < stacks.length; ++i) {
+ t = stacks[i];
+ frame[frameIndex++] = t;
+ if (t == Frame.LONG || t == Frame.DOUBLE) {
+ ++i;
+ }
+ }
+ endFrame();
+ }
+
+ /**
+ * Visit the implicit first frame of this method.
+ */
+ private void visitImplicitFirstFrame() {
+ // There can be at most descriptor.length() + 1 locals
+ int frameIndex = startFrame(0, descriptor.length() + 1, 0);
+ if ((access & Opcodes.ACC_STATIC) == 0) {
+ if ((access & ACC_CONSTRUCTOR) == 0) {
+ frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);
+ } else {
+ frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;
+ }
+ }
+ int i = 1;
+ loop: while (true) {
+ int j = i;
+ switch (descriptor.charAt(i++)) {
+ case 'Z':
+ case 'C':
+ case 'B':
+ case 'S':
+ case 'I':
+ frame[frameIndex++] = 1; // Opcodes.INTEGER;
+ break;
+ case 'F':
+ frame[frameIndex++] = 2; // Opcodes.FLOAT;
+ break;
+ case 'J':
+ frame[frameIndex++] = 4; // Opcodes.LONG;
+ break;
+ case 'D':
+ frame[frameIndex++] = 3; // Opcodes.DOUBLE;
+ break;
+ case '[':
+ while (descriptor.charAt(i) == '[') {
+ ++i;
+ }
+ if (descriptor.charAt(i) == 'L') {
+ ++i;
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j, ++i));
+ break;
+ case 'L':
+ while (descriptor.charAt(i) != ';') {
+ ++i;
+ }
+ frame[frameIndex++] = Frame.OBJECT
+ | cw.addType(descriptor.substring(j + 1, i++));
+ break;
+ default:
+ break loop;
+ }
+ }
+ frame[1] = frameIndex - 3;
+ endFrame();
+ }
+
+ /**
+ * Starts the visit of a stack map frame.
+ *
+ * @param offset
+ * the offset of the instruction to which the frame corresponds.
+ * @param nLocal
+ * the number of local variables in the frame.
+ * @param nStack
+ * the number of stack elements in the frame.
+ * @return the index of the next element to be written in this frame.
+ */
+ private int startFrame(final int offset, final int nLocal, final int nStack) {
+ int n = 3 + nLocal + nStack;
+ if (frame == null || frame.length < n) {
+ frame = new int[n];
+ }
+ frame[0] = offset;
+ frame[1] = nLocal;
+ frame[2] = nStack;
+ return 3;
+ }
+
+ /**
+ * Checks if the visit of the current frame {@link #frame} is finished, and
+ * if yes, write it in the StackMapTable attribute.
+ */
+ private void endFrame() {
+ if (previousFrame != null) { // do not write the first frame
+ if (stackMap == null) {
+ stackMap = new ByteVector();
+ }
+ writeFrame();
+ ++frameCount;
+ }
+ previousFrame = frame;
+ frame = null;
+ }
+
+ /**
+ * Compress and writes the current frame {@link #frame} in the StackMapTable
+ * attribute.
+ */
+ private void writeFrame() {
+ int clocalsSize = frame[1];
+ int cstackSize = frame[2];
+ if ((cw.version & 0xFFFF) < Opcodes.V1_6) {
+ stackMap.putShort(frame[0]).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ return;
+ }
+ int localsSize = previousFrame[1];
+ int type = FULL_FRAME;
+ int k = 0;
+ int delta;
+ if (frameCount == 0) {
+ delta = frame[0];
+ } else {
+ delta = frame[0] - previousFrame[0] - 1;
+ }
+ if (cstackSize == 0) {
+ k = clocalsSize - localsSize;
+ switch (k) {
+ case -3:
+ case -2:
+ case -1:
+ type = CHOP_FRAME;
+ localsSize = clocalsSize;
+ break;
+ case 0:
+ type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;
+ break;
+ case 1:
+ case 2:
+ case 3:
+ type = APPEND_FRAME;
+ break;
+ }
+ } else if (clocalsSize == localsSize && cstackSize == 1) {
+ type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME
+ : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;
+ }
+ if (type != FULL_FRAME) {
+ // verify if locals are the same
+ int l = 3;
+ for (int j = 0; j < localsSize; j++) {
+ if (frame[l] != previousFrame[l]) {
+ type = FULL_FRAME;
+ break;
+ }
+ l++;
+ }
+ }
+ switch (type) {
+ case SAME_FRAME:
+ stackMap.putByte(delta);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:
+ stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(
+ delta);
+ writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);
+ break;
+ case SAME_FRAME_EXTENDED:
+ stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);
+ break;
+ case CHOP_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ break;
+ case APPEND_FRAME:
+ stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);
+ writeFrameTypes(3 + localsSize, 3 + clocalsSize);
+ break;
+ // case FULL_FRAME:
+ default:
+ stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);
+ writeFrameTypes(3, 3 + clocalsSize);
+ stackMap.putShort(cstackSize);
+ writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);
+ }
+ }
+
+ /**
+ * Writes some types of the current frame {@link #frame} into the
+ * StackMapTableAttribute. This method converts types from the format used
+ * in {@link Label} to the format used in StackMapTable attributes. In
+ * particular, it converts type table indexes to constant pool indexes.
+ *
+ * @param start
+ * index of the first type in {@link #frame} to write.
+ * @param end
+ * index of last type in {@link #frame} to write (exclusive).
+ */
+ private void writeFrameTypes(final int start, final int end) {
+ for (int i = start; i < end; ++i) {
+ int t = frame[i];
+ int d = t & Frame.DIM;
+ if (d == 0) {
+ int v = t & Frame.BASE_VALUE;
+ switch (t & Frame.BASE_KIND) {
+ case Frame.OBJECT:
+ stackMap.putByte(7).putShort(
+ cw.newClass(cw.typeTable[v].strVal1));
+ break;
+ case Frame.UNINITIALIZED:
+ stackMap.putByte(8).putShort(cw.typeTable[v].intVal);
+ break;
+ default:
+ stackMap.putByte(v);
+ }
+ } else {
+ StringBuilder sb = new StringBuilder();
+ d >>= 28;
+ while (d-- > 0) {
+ sb.append('[');
+ }
+ if ((t & Frame.BASE_KIND) == Frame.OBJECT) {
+ sb.append('L');
+ sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);
+ sb.append(';');
+ } else {
+ switch (t & 0xF) {
+ case 1:
+ sb.append('I');
+ break;
+ case 2:
+ sb.append('F');
+ break;
+ case 3:
+ sb.append('D');
+ break;
+ case 9:
+ sb.append('Z');
+ break;
+ case 10:
+ sb.append('B');
+ break;
+ case 11:
+ sb.append('C');
+ break;
+ case 12:
+ sb.append('S');
+ break;
+ default:
+ sb.append('J');
+ }
+ }
+ stackMap.putByte(7).putShort(cw.newClass(sb.toString()));
+ }
+ }
+ }
+
+ private void writeFrameType(final Object type) {
+ if (type instanceof String) {
+ stackMap.putByte(7).putShort(cw.newClass((String) type));
+ } else if (type instanceof Integer) {
+ stackMap.putByte(((Integer) type).intValue());
+ } else {
+ stackMap.putByte(8).putShort(((Label) type).position);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: dump bytecode array
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of the bytecode of this method.
+ *
+ * @return the size of the bytecode of this method.
+ */
+ final int getSize() {
+ if (classReaderOffset != 0) {
+ return 6 + classReaderLength;
+ }
+ int size = 8;
+ if (code.length > 0) {
+ if (code.length > 65536) {
+ throw new RuntimeException("Method code too large!");
+ }
+ cw.newUTF8("Code");
+ size += 18 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ cw.newUTF8("LocalVariableTable");
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ cw.newUTF8("LocalVariableTypeTable");
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ cw.newUTF8("LineNumberTable");
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ cw.newUTF8(zip ? "StackMapTable" : "StackMap");
+ size += 8 + stackMap.length;
+ }
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + ictanns.getSize();
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
+ maxLocals);
+ }
+ }
+ if (exceptionCount > 0) {
+ cw.newUTF8("Exceptions");
+ size += 8 + 2 * exceptionCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ cw.newUTF8("Synthetic");
+ size += 6;
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ cw.newUTF8("Deprecated");
+ size += 6;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ cw.newUTF8("Signature");
+ cw.newUTF8(signature);
+ size += 8;
+ }
+ if (methodParameters != null) {
+ cw.newUTF8("MethodParameters");
+ size += 7 + methodParameters.length;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ cw.newUTF8("AnnotationDefault");
+ size += 6 + annd.length;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ cw.newUTF8("RuntimeVisibleAnnotations");
+ size += 8 + anns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ cw.newUTF8("RuntimeInvisibleAnnotations");
+ size += 8 + ianns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ cw.newUTF8("RuntimeVisibleTypeAnnotations");
+ size += 8 + tanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ cw.newUTF8("RuntimeInvisibleTypeAnnotations");
+ size += 8 + itanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ cw.newUTF8("RuntimeVisibleParameterAnnotations");
+ size += 7 + 2 * (panns.length - synthetics);
+ for (int i = panns.length - 1; i >= synthetics; --i) {
+ size += panns[i] == null ? 0 : panns[i].getSize();
+ }
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ cw.newUTF8("RuntimeInvisibleParameterAnnotations");
+ size += 7 + 2 * (ipanns.length - synthetics);
+ for (int i = ipanns.length - 1; i >= synthetics; --i) {
+ size += ipanns[i] == null ? 0 : ipanns[i].getSize();
+ }
+ }
+ if (attrs != null) {
+ size += attrs.getSize(cw, null, 0, -1, -1);
+ }
+ return size;
+ }
+
+ /**
+ * Puts the bytecode of this method in the given byte vector.
+ *
+ * @param out
+ * the byte vector into which the bytecode of this method must be
+ * copied.
+ */
+ final void put(final ByteVector out) {
+ final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;
+ int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED
+ | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE
+ | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);
+ out.putShort(access & ~mask).putShort(name).putShort(desc);
+ if (classReaderOffset != 0) {
+ out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);
+ return;
+ }
+ int attributeCount = 0;
+ if (code.length > 0) {
+ ++attributeCount;
+ }
+ if (exceptionCount > 0) {
+ ++attributeCount;
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ ++attributeCount;
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ ++attributeCount;
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ ++attributeCount;
+ }
+ if (methodParameters != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ ++attributeCount;
+ }
+ if (attrs != null) {
+ attributeCount += attrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (code.length > 0) {
+ int size = 12 + code.length + 8 * handlerCount;
+ if (localVar != null) {
+ size += 8 + localVar.length;
+ }
+ if (localVarType != null) {
+ size += 8 + localVarType.length;
+ }
+ if (lineNumber != null) {
+ size += 8 + lineNumber.length;
+ }
+ if (stackMap != null) {
+ size += 8 + stackMap.length;
+ }
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ size += 8 + ctanns.getSize();
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ size += 8 + ictanns.getSize();
+ }
+ if (cattrs != null) {
+ size += cattrs.getSize(cw, code.data, code.length, maxStack,
+ maxLocals);
+ }
+ out.putShort(cw.newUTF8("Code")).putInt(size);
+ out.putShort(maxStack).putShort(maxLocals);
+ out.putInt(code.length).putByteArray(code.data, 0, code.length);
+ out.putShort(handlerCount);
+ if (handlerCount > 0) {
+ Handler h = firstHandler;
+ while (h != null) {
+ out.putShort(h.start.position).putShort(h.end.position)
+ .putShort(h.handler.position).putShort(h.type);
+ h = h.next;
+ }
+ }
+ attributeCount = 0;
+ if (localVar != null) {
+ ++attributeCount;
+ }
+ if (localVarType != null) {
+ ++attributeCount;
+ }
+ if (lineNumber != null) {
+ ++attributeCount;
+ }
+ if (stackMap != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ ++attributeCount;
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ ++attributeCount;
+ }
+ if (cattrs != null) {
+ attributeCount += cattrs.getCount();
+ }
+ out.putShort(attributeCount);
+ if (localVar != null) {
+ out.putShort(cw.newUTF8("LocalVariableTable"));
+ out.putInt(localVar.length + 2).putShort(localVarCount);
+ out.putByteArray(localVar.data, 0, localVar.length);
+ }
+ if (localVarType != null) {
+ out.putShort(cw.newUTF8("LocalVariableTypeTable"));
+ out.putInt(localVarType.length + 2).putShort(localVarTypeCount);
+ out.putByteArray(localVarType.data, 0, localVarType.length);
+ }
+ if (lineNumber != null) {
+ out.putShort(cw.newUTF8("LineNumberTable"));
+ out.putInt(lineNumber.length + 2).putShort(lineNumberCount);
+ out.putByteArray(lineNumber.data, 0, lineNumber.length);
+ }
+ if (stackMap != null) {
+ boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;
+ out.putShort(cw.newUTF8(zip ? "StackMapTable" : "StackMap"));
+ out.putInt(stackMap.length + 2).putShort(frameCount);
+ out.putByteArray(stackMap.data, 0, stackMap.length);
+ }
+ if (ClassReader.ANNOTATIONS && ctanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ ctanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ictanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ ictanns.put(out);
+ }
+ if (cattrs != null) {
+ cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);
+ }
+ }
+ if (exceptionCount > 0) {
+ out.putShort(cw.newUTF8("Exceptions")).putInt(
+ 2 * exceptionCount + 2);
+ out.putShort(exceptionCount);
+ for (int i = 0; i < exceptionCount; ++i) {
+ out.putShort(exceptions[i]);
+ }
+ }
+ if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+ if ((cw.version & 0xFFFF) < Opcodes.V1_5
+ || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {
+ out.putShort(cw.newUTF8("Synthetic")).putInt(0);
+ }
+ }
+ if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+ out.putShort(cw.newUTF8("Deprecated")).putInt(0);
+ }
+ if (ClassReader.SIGNATURES && signature != null) {
+ out.putShort(cw.newUTF8("Signature")).putInt(2)
+ .putShort(cw.newUTF8(signature));
+ }
+ if (methodParameters != null) {
+ out.putShort(cw.newUTF8("MethodParameters"));
+ out.putInt(methodParameters.length + 1).putByte(
+ methodParametersCount);
+ out.putByteArray(methodParameters.data, 0, methodParameters.length);
+ }
+ if (ClassReader.ANNOTATIONS && annd != null) {
+ out.putShort(cw.newUTF8("AnnotationDefault"));
+ out.putInt(annd.length);
+ out.putByteArray(annd.data, 0, annd.length);
+ }
+ if (ClassReader.ANNOTATIONS && anns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleAnnotations"));
+ anns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && ianns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleAnnotations"));
+ ianns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && tanns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleTypeAnnotations"));
+ tanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && itanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleTypeAnnotations"));
+ itanns.put(out);
+ }
+ if (ClassReader.ANNOTATIONS && panns != null) {
+ out.putShort(cw.newUTF8("RuntimeVisibleParameterAnnotations"));
+ AnnotationWriter.put(panns, synthetics, out);
+ }
+ if (ClassReader.ANNOTATIONS && ipanns != null) {
+ out.putShort(cw.newUTF8("RuntimeInvisibleParameterAnnotations"));
+ AnnotationWriter.put(ipanns, synthetics, out);
+ }
+ if (attrs != null) {
+ attrs.put(cw, null, 0, -1, -1, out);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)
+ // ------------------------------------------------------------------------
+
+ /**
+ * Resizes and replaces the temporary instructions inserted by
+ * {@link Label#resolve} for wide forward jumps, while keeping jump offsets
+ * and instruction addresses consistent. This may require to resize other
+ * existing instructions, or even to introduce new instructions: for
+ * example, increasing the size of an instruction by 2 at the middle of a
+ * method can increases the offset of an IFEQ instruction from 32766 to
+ * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W
+ * 32765. This, in turn, may require to increase the size of another jump
+ * instruction, and so on... All these operations are handled automatically
+ * by this method.
+ * <p>
+ * <i>This method must be called after all the method that is being built
+ * has been visited</i>. In particular, the {@link Label Label} objects used
+ * to construct the method are no longer valid after this method has been
+ * called.
+ */
+ private void resizeInstructions() {
+ byte[] b = code.data; // bytecode of the method
+ int u, v, label; // indexes in b
+ int i, j; // loop indexes
+ /*
+ * 1st step: As explained above, resizing an instruction may require to
+ * resize another one, which may require to resize yet another one, and
+ * so on. The first step of the algorithm consists in finding all the
+ * instructions that need to be resized, without modifying the code.
+ * This is done by the following "fix point" algorithm:
+ *
+ * Parse the code to find the jump instructions whose offset will need
+ * more than 2 bytes to be stored (the future offset is computed from
+ * the current offset and from the number of bytes that will be inserted
+ * or removed between the source and target instructions). For each such
+ * instruction, adds an entry in (a copy of) the indexes and sizes
+ * arrays (if this has not already been done in a previous iteration!).
+ *
+ * If at least one entry has been added during the previous step, go
+ * back to the beginning, otherwise stop.
+ *
+ * In fact the real algorithm is complicated by the fact that the size
+ * of TABLESWITCH and LOOKUPSWITCH instructions depends on their
+ * position in the bytecode (because of padding). In order to ensure the
+ * convergence of the algorithm, the number of bytes to be added or
+ * removed from these instructions is over estimated during the previous
+ * loop, and computed exactly only after the loop is finished (this
+ * requires another pass to parse the bytecode of the method).
+ */
+ int[] allIndexes = new int[0]; // copy of indexes
+ int[] allSizes = new int[0]; // copy of sizes
+ boolean[] resize; // instructions to be resized
+ int newOffset; // future offset of a jump instruction
+
+ resize = new boolean[code.length];
+
+ // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done
+ int state = 3;
+ do {
+ if (state == 3) {
+ state = 2;
+ }
+ u = 0;
+ while (u < b.length) {
+ int opcode = b[u] & 0xFF; // opcode of current instruction
+ int insert = 0; // bytes to be added after this instruction
+
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // converts temporary opcodes 202 to 217, 218 and
+ // 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (newOffset < Short.MIN_VALUE
+ || newOffset > Short.MAX_VALUE) {
+ if (!resize[u]) {
+ if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {
+ // two additional bytes will be required to
+ // replace this GOTO or JSR instruction with
+ // a GOTO_W or a JSR_W
+ insert = 2;
+ } else {
+ // five additional bytes will be required to
+ // replace this IFxxx <l> instruction with
+ // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx
+ // is the "opposite" opcode of IFxxx (i.e.,
+ // IFNE for IFEQ) and where <l'> designates
+ // the instruction just after the GOTO_W.
+ insert = 5;
+ }
+ resize[u] = true;
+ }
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ if (state == 1) {
+ // true number of bytes to be added (or removed)
+ // from this instruction = (future number of padding
+ // bytes - current number of padding byte) -
+ // previously over estimated variation =
+ // = ((3 - newOffset%4) - (3 - u%4)) - u%4
+ // = (-newOffset%4 + u%4) - u%4
+ // = -(newOffset & 3)
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // over estimation of the number of bytes to be
+ // added to this instruction = 3 - current number
+ // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;
+ break;
+ case ClassWriter.LOOK_INSN:
+ if (state == 1) {
+ // like TABL_INSN
+ newOffset = getNewOffset(allIndexes, allSizes, 0, u);
+ insert = -(newOffset & 3);
+ } else if (!resize[u]) {
+ // like TABL_INSN
+ insert = u & 3;
+ resize[u] = true;
+ }
+ // skips instruction
+ u = u + 4 - (u & 3);
+ u += 8 * readInt(b, u + 4) + 8;
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ u += 6;
+ } else {
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ u += 5;
+ break;
+ // case ClassWriter.MANA_INSN:
+ default:
+ u += 4;
+ break;
+ }
+ if (insert != 0) {
+ // adds a new (u, insert) entry in the allIndexes and
+ // allSizes arrays
+ int[] newIndexes = new int[allIndexes.length + 1];
+ int[] newSizes = new int[allSizes.length + 1];
+ System.arraycopy(allIndexes, 0, newIndexes, 0,
+ allIndexes.length);
+ System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);
+ newIndexes[allIndexes.length] = u;
+ newSizes[allSizes.length] = insert;
+ allIndexes = newIndexes;
+ allSizes = newSizes;
+ if (insert > 0) {
+ state = 3;
+ }
+ }
+ }
+ if (state < 3) {
+ --state;
+ }
+ } while (state != 0);
+
+ // 2nd step:
+ // copies the bytecode of the method into a new bytevector, updates the
+ // offsets, and inserts (or removes) bytes as requested.
+
+ ByteVector newCode = new ByteVector(code.length);
+
+ u = 0;
+ while (u < code.length) {
+ int opcode = b[u] & 0xFF;
+ switch (ClassWriter.TYPE[opcode]) {
+ case ClassWriter.NOARG_INSN:
+ case ClassWriter.IMPLVAR_INSN:
+ newCode.putByte(opcode);
+ u += 1;
+ break;
+ case ClassWriter.LABEL_INSN:
+ if (opcode > 201) {
+ // changes temporary opcodes 202 to 217 (inclusive), 218
+ // and 219 to IFEQ ... JSR (inclusive), IFNULL and
+ // IFNONNULL
+ opcode = opcode < 218 ? opcode - 49 : opcode - 20;
+ label = u + readUnsignedShort(b, u + 1);
+ } else {
+ label = u + readShort(b, u + 1);
+ }
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ if (resize[u]) {
+ // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx
+ // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is
+ // the "opposite" opcode of IFxxx (i.e., IFNE for IFEQ)
+ // and where <l'> designates the instruction just after
+ // the GOTO_W.
+ if (opcode == Opcodes.GOTO) {
+ newCode.putByte(200); // GOTO_W
+ } else if (opcode == Opcodes.JSR) {
+ newCode.putByte(201); // JSR_W
+ } else {
+ newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1
+ : opcode ^ 1);
+ newCode.putShort(8); // jump offset
+ newCode.putByte(200); // GOTO_W
+ // newOffset now computed from start of GOTO_W
+ newOffset -= 3;
+ }
+ newCode.putInt(newOffset);
+ } else {
+ newCode.putByte(opcode);
+ newCode.putShort(newOffset);
+ }
+ u += 3;
+ break;
+ case ClassWriter.LABELW_INSN:
+ label = u + readInt(b, u + 1);
+ newOffset = getNewOffset(allIndexes, allSizes, u, label);
+ newCode.putByte(opcode);
+ newCode.putInt(newOffset);
+ u += 5;
+ break;
+ case ClassWriter.TABL_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.TABLESWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ j = readInt(b, u) - j + 1;
+ u += 4;
+ newCode.putInt(readInt(b, u - 4));
+ for (; j > 0; --j) {
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.LOOK_INSN:
+ // skips 0 to 3 padding bytes
+ v = u;
+ u = u + 4 - (v & 3);
+ // reads and copies instruction
+ newCode.putByte(Opcodes.LOOKUPSWITCH);
+ newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ j = readInt(b, u);
+ u += 4;
+ newCode.putInt(j);
+ for (; j > 0; --j) {
+ newCode.putInt(readInt(b, u));
+ u += 4;
+ label = v + readInt(b, u);
+ u += 4;
+ newOffset = getNewOffset(allIndexes, allSizes, v, label);
+ newCode.putInt(newOffset);
+ }
+ break;
+ case ClassWriter.WIDE_INSN:
+ opcode = b[u + 1] & 0xFF;
+ if (opcode == Opcodes.IINC) {
+ newCode.putByteArray(b, u, 6);
+ u += 6;
+ } else {
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ }
+ break;
+ case ClassWriter.VAR_INSN:
+ case ClassWriter.SBYTE_INSN:
+ case ClassWriter.LDC_INSN:
+ newCode.putByteArray(b, u, 2);
+ u += 2;
+ break;
+ case ClassWriter.SHORT_INSN:
+ case ClassWriter.LDCW_INSN:
+ case ClassWriter.FIELDORMETH_INSN:
+ case ClassWriter.TYPE_INSN:
+ case ClassWriter.IINC_INSN:
+ newCode.putByteArray(b, u, 3);
+ u += 3;
+ break;
+ case ClassWriter.ITFMETH_INSN:
+ case ClassWriter.INDYMETH_INSN:
+ newCode.putByteArray(b, u, 5);
+ u += 5;
+ break;
+ // case MANA_INSN:
+ default:
+ newCode.putByteArray(b, u, 4);
+ u += 4;
+ break;
+ }
+ }
+
+ // updates the stack map frame labels
+ if (compute == FRAMES) {
+ Label l = labels;
+ while (l != null) {
+ /*
+ * Detects the labels that are just after an IF instruction that
+ * has been resized with the IFNOT GOTO_W pattern. These labels
+ * are now the target of a jump instruction (the IFNOT
+ * instruction). Note that we need the original label position
+ * here. getNewOffset must therefore never have been called for
+ * this label.
+ */
+ u = l.position - 3;
+ if (u >= 0 && resize[u]) {
+ l.status |= Label.TARGET;
+ }
+ getNewOffset(allIndexes, allSizes, l);
+ l = l.successor;
+ }
+ // Update the offsets in the uninitialized types
+ if (cw.typeTable != null) {
+ for (i = 0; i < cw.typeTable.length; ++i) {
+ Item item = cw.typeTable[i];
+ if (item != null && item.type == ClassWriter.TYPE_UNINIT) {
+ item.intVal = getNewOffset(allIndexes, allSizes, 0,
+ item.intVal);
+ }
+ }
+ }
+ // The stack map frames are not serialized yet, so we don't need
+ // to update them. They will be serialized in visitMaxs.
+ } else if (frameCount > 0) {
+ /*
+ * Resizing an existing stack map frame table is really hard. Not
+ * only the table must be parsed to update the offets, but new
+ * frames may be needed for jump instructions that were inserted by
+ * this method. And updating the offsets or inserting frames can
+ * change the format of the following frames, in case of packed
+ * frames. In practice the whole table must be recomputed. For this
+ * the frames are marked as potentially invalid. This will cause the
+ * whole class to be reread and rewritten with the COMPUTE_FRAMES
+ * option (see the ClassWriter.toByteArray method). This is not very
+ * efficient but is much easier and requires much less code than any
+ * other method I can think of.
+ */
+ cw.invalidFrames = true;
+ }
+ // updates the exception handler block labels
+ Handler h = firstHandler;
+ while (h != null) {
+ getNewOffset(allIndexes, allSizes, h.start);
+ getNewOffset(allIndexes, allSizes, h.end);
+ getNewOffset(allIndexes, allSizes, h.handler);
+ h = h.next;
+ }
+ // updates the instructions addresses in the
+ // local var and line number tables
+ for (i = 0; i < 2; ++i) {
+ ByteVector bv = i == 0 ? localVar : localVarType;
+ if (bv != null) {
+ b = bv.data;
+ u = 0;
+ while (u < bv.length) {
+ label = readUnsignedShort(b, u);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label);
+ writeShort(b, u, newOffset);
+ label += readUnsignedShort(b, u + 2);
+ newOffset = getNewOffset(allIndexes, allSizes, 0, label)
+ - newOffset;
+ writeShort(b, u + 2, newOffset);
+ u += 10;
+ }
+ }
+ }
+ if (lineNumber != null) {
+ b = lineNumber.data;
+ u = 0;
+ while (u < lineNumber.length) {
+ writeShort(
+ b,
+ u,
+ getNewOffset(allIndexes, allSizes, 0,
+ readUnsignedShort(b, u)));
+ u += 4;
+ }
+ }
+ // updates the labels of the other attributes
+ Attribute attr = cattrs;
+ while (attr != null) {
+ Label[] labels = attr.getLabels();
+ if (labels != null) {
+ for (i = labels.length - 1; i >= 0; --i) {
+ getNewOffset(allIndexes, allSizes, labels[i]);
+ }
+ }
+ attr = attr.next;
+ }
+
+ // replaces old bytecodes with new ones
+ code = newCode;
+ }
+
+ /**
+ * Reads an unsigned short value in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readUnsignedShort(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);
+ }
+
+ /**
+ * Reads a signed short value in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
+ * @return the read value.
+ */
+ static short readShort(final byte[] b, final int index) {
+ return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));
+ }
+
+ /**
+ * Reads a signed int value in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * the start index of the value to be read.
+ * @return the read value.
+ */
+ static int readInt(final byte[] b, final int index) {
+ return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)
+ | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);
+ }
+
+ /**
+ * Writes a short value in the given byte array.
+ *
+ * @param b
+ * a byte array.
+ * @param index
+ * where the first byte of the short value must be written.
+ * @param s
+ * the value to be written in the given byte array.
+ */
+ static void writeShort(final byte[] b, final int index, final int s) {
+ b[index] = (byte) (s >>> 8);
+ b[index + 1] = (byte) s;
+ }
+
+ /**
+ * Computes the future value of a bytecode offset.
+ * <p>
+ * Note: it is possible to have several entries for the same instruction in
+ * the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b) and
+ * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').
+ *
+ * @param indexes
+ * current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the
+ * <i>first</i> byte of the <i>next</i> instruction).
+ * @param sizes
+ * the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |
+ * <tt>sizes[i]</tt>| bytes of the instruction will be removed
+ * (the instruction size <i>must not</i> become negative or
+ * null).
+ * @param begin
+ * index of the first byte of the source instruction.
+ * @param end
+ * index of the first byte of the target instruction.
+ * @return the future value of the given bytecode offset.
+ */
+ static int getNewOffset(final int[] indexes, final int[] sizes,
+ final int begin, final int end) {
+ int offset = end - begin;
+ for (int i = 0; i < indexes.length; ++i) {
+ if (begin < indexes[i] && indexes[i] <= end) {
+ // forward jump
+ offset += sizes[i];
+ } else if (end < indexes[i] && indexes[i] <= begin) {
+ // backward jump
+ offset -= sizes[i];
+ }
+ }
+ return offset;
+ }
+
+ /**
+ * Updates the offset of the given label.
+ *
+ * @param indexes
+ * current positions of the instructions to be resized. Each
+ * instruction must be designated by the index of its <i>last</i>
+ * byte, plus one (or, in other words, by the index of the
+ * <i>first</i> byte of the <i>next</i> instruction).
+ * @param sizes
+ * the number of bytes to be <i>added</i> to the above
+ * instructions. More precisely, for each i < <tt>len</tt>,
+ * <tt>sizes</tt>[i] bytes will be added at the end of the
+ * instruction designated by <tt>indexes</tt>[i] or, if
+ * <tt>sizes</tt>[i] is negative, the <i>last</i> |
+ * <tt>sizes[i]</tt>| bytes of the instruction will be removed
+ * (the instruction size <i>must not</i> become negative or
+ * null).
+ * @param label
+ * the label whose offset must be updated.
+ */
+ static void getNewOffset(final int[] indexes, final int[] sizes,
+ final Label label) {
+ if ((label.status & Label.RESIZED) == 0) {
+ label.position = getNewOffset(indexes, sizes, 0, label.position);
+ label.status |= Label.RESIZED;
+ }
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Opcodes.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Opcodes.java
new file mode 100644
index 0000000..7d8563b
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Opcodes.java
@@ -0,0 +1,361 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+/**
+ * Defines the JVM opcodes, access flags and array type codes. This interface
+ * does not define all the JVM opcodes because some opcodes are automatically
+ * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced
+ * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n
+ * opcodes are therefore not defined in this interface. Likewise for LDC,
+ * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and
+ * JSR_W.
+ *
+ * @author Eric Bruneton
+ * @author Eugene Kuleshov
+ */
+public interface Opcodes {
+
+ // ASM API versions
+
+ int ASM4 = 4 << 16 | 0 << 8 | 0;
+ int ASM5 = 5 << 16 | 0 << 8 | 0;
+
+ // versions
+
+ int V1_1 = 3 << 16 | 45;
+ int V1_2 = 0 << 16 | 46;
+ int V1_3 = 0 << 16 | 47;
+ int V1_4 = 0 << 16 | 48;
+ int V1_5 = 0 << 16 | 49;
+ int V1_6 = 0 << 16 | 50;
+ int V1_7 = 0 << 16 | 51;
+ int V1_8 = 0 << 16 | 52;
+
+ // access flags
+
+ int ACC_PUBLIC = 0x0001; // class, field, method
+ int ACC_PRIVATE = 0x0002; // class, field, method
+ int ACC_PROTECTED = 0x0004; // class, field, method
+ int ACC_STATIC = 0x0008; // field, method
+ int ACC_FINAL = 0x0010; // class, field, method, parameter
+ int ACC_SUPER = 0x0020; // class
+ int ACC_SYNCHRONIZED = 0x0020; // method
+ int ACC_VOLATILE = 0x0040; // field
+ int ACC_BRIDGE = 0x0040; // method
+ int ACC_VARARGS = 0x0080; // method
+ int ACC_TRANSIENT = 0x0080; // field
+ int ACC_NATIVE = 0x0100; // method
+ int ACC_INTERFACE = 0x0200; // class
+ int ACC_ABSTRACT = 0x0400; // class, method
+ int ACC_STRICT = 0x0800; // method
+ int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter
+ int ACC_ANNOTATION = 0x2000; // class
+ int ACC_ENUM = 0x4000; // class(?) field inner
+ int ACC_MANDATED = 0x8000; // parameter
+
+ // ASM specific pseudo access flags
+
+ int ACC_DEPRECATED = 0x20000; // class, field, method
+
+ // types for NEWARRAY
+
+ int T_BOOLEAN = 4;
+ int T_CHAR = 5;
+ int T_FLOAT = 6;
+ int T_DOUBLE = 7;
+ int T_BYTE = 8;
+ int T_SHORT = 9;
+ int T_INT = 10;
+ int T_LONG = 11;
+
+ // tags for Handle
+
+ int H_GETFIELD = 1;
+ int H_GETSTATIC = 2;
+ int H_PUTFIELD = 3;
+ int H_PUTSTATIC = 4;
+ int H_INVOKEVIRTUAL = 5;
+ int H_INVOKESTATIC = 6;
+ int H_INVOKESPECIAL = 7;
+ int H_NEWINVOKESPECIAL = 8;
+ int H_INVOKEINTERFACE = 9;
+
+ // stack map frame types
+
+ /**
+ * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.
+ */
+ int F_NEW = -1;
+
+ /**
+ * Represents a compressed frame with complete frame data.
+ */
+ int F_FULL = 0;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that additional 1-3 locals are defined, and
+ * with an empty stack.
+ */
+ int F_APPEND = 1;
+
+ /**
+ * Represents a compressed frame where locals are the same as the locals in
+ * the previous frame, except that the last 1-3 locals are absent and with
+ * an empty stack.
+ */
+ int F_CHOP = 2;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with an empty stack.
+ */
+ int F_SAME = 3;
+
+ /**
+ * Represents a compressed frame with exactly the same locals as the
+ * previous frame and with a single value on the stack.
+ */
+ int F_SAME1 = 4;
+
+ Integer TOP = new Integer(0);
+ Integer INTEGER = new Integer(1);
+ Integer FLOAT = new Integer(2);
+ Integer DOUBLE = new Integer(3);
+ Integer LONG = new Integer(4);
+ Integer NULL = new Integer(5);
+ Integer UNINITIALIZED_THIS = new Integer(6);
+
+ // opcodes // visit method (- = idem)
+
+ int NOP = 0; // visitInsn
+ int ACONST_NULL = 1; // -
+ int ICONST_M1 = 2; // -
+ int ICONST_0 = 3; // -
+ int ICONST_1 = 4; // -
+ int ICONST_2 = 5; // -
+ int ICONST_3 = 6; // -
+ int ICONST_4 = 7; // -
+ int ICONST_5 = 8; // -
+ int LCONST_0 = 9; // -
+ int LCONST_1 = 10; // -
+ int FCONST_0 = 11; // -
+ int FCONST_1 = 12; // -
+ int FCONST_2 = 13; // -
+ int DCONST_0 = 14; // -
+ int DCONST_1 = 15; // -
+ int BIPUSH = 16; // visitIntInsn
+ int SIPUSH = 17; // -
+ int LDC = 18; // visitLdcInsn
+ // int LDC_W = 19; // -
+ // int LDC2_W = 20; // -
+ int ILOAD = 21; // visitVarInsn
+ int LLOAD = 22; // -
+ int FLOAD = 23; // -
+ int DLOAD = 24; // -
+ int ALOAD = 25; // -
+ // int ILOAD_0 = 26; // -
+ // int ILOAD_1 = 27; // -
+ // int ILOAD_2 = 28; // -
+ // int ILOAD_3 = 29; // -
+ // int LLOAD_0 = 30; // -
+ // int LLOAD_1 = 31; // -
+ // int LLOAD_2 = 32; // -
+ // int LLOAD_3 = 33; // -
+ // int FLOAD_0 = 34; // -
+ // int FLOAD_1 = 35; // -
+ // int FLOAD_2 = 36; // -
+ // int FLOAD_3 = 37; // -
+ // int DLOAD_0 = 38; // -
+ // int DLOAD_1 = 39; // -
+ // int DLOAD_2 = 40; // -
+ // int DLOAD_3 = 41; // -
+ // int ALOAD_0 = 42; // -
+ // int ALOAD_1 = 43; // -
+ // int ALOAD_2 = 44; // -
+ // int ALOAD_3 = 45; // -
+ int IALOAD = 46; // visitInsn
+ int LALOAD = 47; // -
+ int FALOAD = 48; // -
+ int DALOAD = 49; // -
+ int AALOAD = 50; // -
+ int BALOAD = 51; // -
+ int CALOAD = 52; // -
+ int SALOAD = 53; // -
+ int ISTORE = 54; // visitVarInsn
+ int LSTORE = 55; // -
+ int FSTORE = 56; // -
+ int DSTORE = 57; // -
+ int ASTORE = 58; // -
+ // int ISTORE_0 = 59; // -
+ // int ISTORE_1 = 60; // -
+ // int ISTORE_2 = 61; // -
+ // int ISTORE_3 = 62; // -
+ // int LSTORE_0 = 63; // -
+ // int LSTORE_1 = 64; // -
+ // int LSTORE_2 = 65; // -
+ // int LSTORE_3 = 66; // -
+ // int FSTORE_0 = 67; // -
+ // int FSTORE_1 = 68; // -
+ // int FSTORE_2 = 69; // -
+ // int FSTORE_3 = 70; // -
+ // int DSTORE_0 = 71; // -
+ // int DSTORE_1 = 72; // -
+ // int DSTORE_2 = 73; // -
+ // int DSTORE_3 = 74; // -
+ // int ASTORE_0 = 75; // -
+ // int ASTORE_1 = 76; // -
+ // int ASTORE_2 = 77; // -
+ // int ASTORE_3 = 78; // -
+ int IASTORE = 79; // visitInsn
+ int LASTORE = 80; // -
+ int FASTORE = 81; // -
+ int DASTORE = 82; // -
+ int AASTORE = 83; // -
+ int BASTORE = 84; // -
+ int CASTORE = 85; // -
+ int SASTORE = 86; // -
+ int POP = 87; // -
+ int POP2 = 88; // -
+ int DUP = 89; // -
+ int DUP_X1 = 90; // -
+ int DUP_X2 = 91; // -
+ int DUP2 = 92; // -
+ int DUP2_X1 = 93; // -
+ int DUP2_X2 = 94; // -
+ int SWAP = 95; // -
+ int IADD = 96; // -
+ int LADD = 97; // -
+ int FADD = 98; // -
+ int DADD = 99; // -
+ int ISUB = 100; // -
+ int LSUB = 101; // -
+ int FSUB = 102; // -
+ int DSUB = 103; // -
+ int IMUL = 104; // -
+ int LMUL = 105; // -
+ int FMUL = 106; // -
+ int DMUL = 107; // -
+ int IDIV = 108; // -
+ int LDIV = 109; // -
+ int FDIV = 110; // -
+ int DDIV = 111; // -
+ int IREM = 112; // -
+ int LREM = 113; // -
+ int FREM = 114; // -
+ int DREM = 115; // -
+ int INEG = 116; // -
+ int LNEG = 117; // -
+ int FNEG = 118; // -
+ int DNEG = 119; // -
+ int ISHL = 120; // -
+ int LSHL = 121; // -
+ int ISHR = 122; // -
+ int LSHR = 123; // -
+ int IUSHR = 124; // -
+ int LUSHR = 125; // -
+ int IAND = 126; // -
+ int LAND = 127; // -
+ int IOR = 128; // -
+ int LOR = 129; // -
+ int IXOR = 130; // -
+ int LXOR = 131; // -
+ int IINC = 132; // visitIincInsn
+ int I2L = 133; // visitInsn
+ int I2F = 134; // -
+ int I2D = 135; // -
+ int L2I = 136; // -
+ int L2F = 137; // -
+ int L2D = 138; // -
+ int F2I = 139; // -
+ int F2L = 140; // -
+ int F2D = 141; // -
+ int D2I = 142; // -
+ int D2L = 143; // -
+ int D2F = 144; // -
+ int I2B = 145; // -
+ int I2C = 146; // -
+ int I2S = 147; // -
+ int LCMP = 148; // -
+ int FCMPL = 149; // -
+ int FCMPG = 150; // -
+ int DCMPL = 151; // -
+ int DCMPG = 152; // -
+ int IFEQ = 153; // visitJumpInsn
+ int IFNE = 154; // -
+ int IFLT = 155; // -
+ int IFGE = 156; // -
+ int IFGT = 157; // -
+ int IFLE = 158; // -
+ int IF_ICMPEQ = 159; // -
+ int IF_ICMPNE = 160; // -
+ int IF_ICMPLT = 161; // -
+ int IF_ICMPGE = 162; // -
+ int IF_ICMPGT = 163; // -
+ int IF_ICMPLE = 164; // -
+ int IF_ACMPEQ = 165; // -
+ int IF_ACMPNE = 166; // -
+ int GOTO = 167; // -
+ int JSR = 168; // -
+ int RET = 169; // visitVarInsn
+ int TABLESWITCH = 170; // visiTableSwitchInsn
+ int LOOKUPSWITCH = 171; // visitLookupSwitch
+ int IRETURN = 172; // visitInsn
+ int LRETURN = 173; // -
+ int FRETURN = 174; // -
+ int DRETURN = 175; // -
+ int ARETURN = 176; // -
+ int RETURN = 177; // -
+ int GETSTATIC = 178; // visitFieldInsn
+ int PUTSTATIC = 179; // -
+ int GETFIELD = 180; // -
+ int PUTFIELD = 181; // -
+ int INVOKEVIRTUAL = 182; // visitMethodInsn
+ int INVOKESPECIAL = 183; // -
+ int INVOKESTATIC = 184; // -
+ int INVOKEINTERFACE = 185; // -
+ int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn
+ int NEW = 187; // visitTypeInsn
+ int NEWARRAY = 188; // visitIntInsn
+ int ANEWARRAY = 189; // visitTypeInsn
+ int ARRAYLENGTH = 190; // visitInsn
+ int ATHROW = 191; // -
+ int CHECKCAST = 192; // visitTypeInsn
+ int INSTANCEOF = 193; // -
+ int MONITORENTER = 194; // visitInsn
+ int MONITOREXIT = 195; // -
+ // int WIDE = 196; // NOT VISITED
+ int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn
+ int IFNULL = 198; // visitJumpInsn
+ int IFNONNULL = 199; // -
+ // int GOTO_W = 200; // -
+ // int JSR_W = 201; // -
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Type.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Type.java
new file mode 100644
index 0000000..c1c7096
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/Type.java
@@ -0,0 +1,896 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.powermock.objectweb.asm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * A Java field or method type. This class can be used to make it easier to
+ * manipulate type and method descriptors.
+ *
+ * @author Eric Bruneton
+ * @author Chris Nokleberg
+ */
+public class Type {
+
+ /**
+ * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int VOID = 0;
+
+ /**
+ * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BOOLEAN = 1;
+
+ /**
+ * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int CHAR = 2;
+
+ /**
+ * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int BYTE = 3;
+
+ /**
+ * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int SHORT = 4;
+
+ /**
+ * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int INT = 5;
+
+ /**
+ * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int FLOAT = 6;
+
+ /**
+ * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int LONG = 7;
+
+ /**
+ * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.
+ */
+ public static final int DOUBLE = 8;
+
+ /**
+ * The sort of array reference types. See {@link #getSort getSort}.
+ */
+ public static final int ARRAY = 9;
+
+ /**
+ * The sort of object reference types. See {@link #getSort getSort}.
+ */
+ public static final int OBJECT = 10;
+
+ /**
+ * The sort of method types. See {@link #getSort getSort}.
+ */
+ public static final int METHOD = 11;
+
+ /**
+ * The <tt>void</tt> type.
+ */
+ public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)
+ | (5 << 16) | (0 << 8) | 0, 1);
+
+ /**
+ * The <tt>boolean</tt> type.
+ */
+ public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)
+ | (0 << 16) | (5 << 8) | 1, 1);
+
+ /**
+ * The <tt>char</tt> type.
+ */
+ public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)
+ | (0 << 16) | (6 << 8) | 1, 1);
+
+ /**
+ * The <tt>byte</tt> type.
+ */
+ public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)
+ | (0 << 16) | (5 << 8) | 1, 1);
+
+ /**
+ * The <tt>short</tt> type.
+ */
+ public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)
+ | (0 << 16) | (7 << 8) | 1, 1);
+
+ /**
+ * The <tt>int</tt> type.
+ */
+ public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)
+ | (0 << 16) | (0 << 8) | 1, 1);
+
+ /**
+ * The <tt>float</tt> type.
+ */
+ public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)
+ | (2 << 16) | (2 << 8) | 1, 1);
+
+ /**
+ * The <tt>long</tt> type.
+ */
+ public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)
+ | (1 << 16) | (1 << 8) | 2, 1);
+
+ /**
+ * The <tt>double</tt> type.
+ */
+ public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)
+ | (3 << 16) | (3 << 8) | 2, 1);
+
+ // ------------------------------------------------------------------------
+ // Fields
+ // ------------------------------------------------------------------------
+
+ /**
+ * The sort of this Java type.
+ */
+ private final int sort;
+
+ /**
+ * A buffer containing the internal name of this Java type. This field is
+ * only used for reference types.
+ */
+ private final char[] buf;
+
+ /**
+ * The offset of the internal name of this Java type in {@link #buf buf} or,
+ * for primitive types, the size, descriptor and getOpcode offsets for this
+ * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset
+ * for IALOAD or IASTORE, byte 3 the offset for all other instructions).
+ */
+ private final int off;
+
+ /**
+ * The length of the internal name of this Java type.
+ */
+ private final int len;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructs a reference type.
+ *
+ * @param sort
+ * the sort of the reference type to be constructed.
+ * @param buf
+ * a buffer containing the descriptor of the previous type.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
+ * @param len
+ * the length of this descriptor.
+ */
+ private Type(final int sort, final char[] buf, final int off, final int len) {
+ this.sort = sort;
+ this.buf = buf;
+ this.off = off;
+ this.len = len;
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor.
+ *
+ * @param typeDescriptor
+ * a field or method type descriptor.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ public static Type getType(final String typeDescriptor) {
+ return getType(typeDescriptor.toCharArray(), 0);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given internal name.
+ *
+ * @param internalName
+ * an internal name.
+ * @return the Java type corresponding to the given internal name.
+ */
+ public static Type getObjectType(final String internalName) {
+ char[] buf = internalName.toCharArray();
+ return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);
+ }
+
+ /**
+ * Returns the Java type corresponding to the given method descriptor.
+ * Equivalent to <code>Type.getType(methodDescriptor)</code>.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
+ * @return the Java type corresponding to the given method descriptor.
+ */
+ public static Type getMethodType(final String methodDescriptor) {
+ return getType(methodDescriptor.toCharArray(), 0);
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given argument and
+ * return types.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
+ * @return the Java type corresponding to the given argument and return
+ * types.
+ */
+ public static Type getMethodType(final Type returnType,
+ final Type... argumentTypes) {
+ return getType(getMethodDescriptor(returnType, argumentTypes));
+ }
+
+ /**
+ * Returns the Java type corresponding to the given class.
+ *
+ * @param c
+ * a class.
+ * @return the Java type corresponding to the given class.
+ */
+ public static Type getType(final Class<?> c) {
+ if (c.isPrimitive()) {
+ if (c == Integer.TYPE) {
+ return INT_TYPE;
+ } else if (c == Void.TYPE) {
+ return VOID_TYPE;
+ } else if (c == Boolean.TYPE) {
+ return BOOLEAN_TYPE;
+ } else if (c == Byte.TYPE) {
+ return BYTE_TYPE;
+ } else if (c == Character.TYPE) {
+ return CHAR_TYPE;
+ } else if (c == Short.TYPE) {
+ return SHORT_TYPE;
+ } else if (c == Double.TYPE) {
+ return DOUBLE_TYPE;
+ } else if (c == Float.TYPE) {
+ return FLOAT_TYPE;
+ } else /* if (c == Long.TYPE) */{
+ return LONG_TYPE;
+ }
+ } else {
+ return getType(getDescriptor(c));
+ }
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given constructor.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
+ * @return the Java method type corresponding to the given constructor.
+ */
+ public static Type getType(final Constructor<?> c) {
+ return getType(getConstructorDescriptor(c));
+ }
+
+ /**
+ * Returns the Java method type corresponding to the given method.
+ *
+ * @param m
+ * a {@link Method Method} object.
+ * @return the Java method type corresponding to the given method.
+ */
+ public static Type getType(final Method m) {
+ return getType(getMethodDescriptor(m));
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
+ * @return the Java types corresponding to the argument types of the given
+ * method descriptor.
+ */
+ public static Type[] getArgumentTypes(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ int off = 1;
+ int size = 0;
+ while (true) {
+ char car = buf[off++];
+ if (car == ')') {
+ break;
+ } else if (car == 'L') {
+ while (buf[off++] != ';') {
+ }
+ ++size;
+ } else if (car != '[') {
+ ++size;
+ }
+ }
+ Type[] args = new Type[size];
+ off = 1;
+ size = 0;
+ while (buf[off] != ')') {
+ args[size] = getType(buf, off);
+ off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);
+ size += 1;
+ }
+ return args;
+ }
+
+ /**
+ * Returns the Java types corresponding to the argument types of the given
+ * method.
+ *
+ * @param method
+ * a method.
+ * @return the Java types corresponding to the argument types of the given
+ * method.
+ */
+ public static Type[] getArgumentTypes(final Method method) {
+ Class<?>[] classes = method.getParameterTypes();
+ Type[] types = new Type[classes.length];
+ for (int i = classes.length - 1; i >= 0; --i) {
+ types[i] = getType(classes[i]);
+ }
+ return types;
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method descriptor.
+ *
+ * @param methodDescriptor
+ * a method descriptor.
+ * @return the Java type corresponding to the return type of the given
+ * method descriptor.
+ */
+ public static Type getReturnType(final String methodDescriptor) {
+ char[] buf = methodDescriptor.toCharArray();
+ return getType(buf, methodDescriptor.indexOf(')') + 1);
+ }
+
+ /**
+ * Returns the Java type corresponding to the return type of the given
+ * method.
+ *
+ * @param method
+ * a method.
+ * @return the Java type corresponding to the return type of the given
+ * method.
+ */
+ public static Type getReturnType(final Method method) {
+ return getType(method.getReturnType());
+ }
+
+ /**
+ * Computes the size of the arguments and of the return value of a method.
+ *
+ * @param desc
+ * the descriptor of a method.
+ * @return the size of the arguments of the method (plus one for the
+ * implicit this argument), argSize, and the size of its return
+ * value, retSize, packed into a single int i =
+ * <tt>(argSize << 2) | retSize</tt> (argSize is therefore equal to
+ * <tt>i >> 2</tt>, and retSize to <tt>i & 0x03</tt>).
+ */
+ public static int getArgumentsAndReturnSizes(final String desc) {
+ int n = 1;
+ int c = 1;
+ while (true) {
+ char car = desc.charAt(c++);
+ if (car == ')') {
+ car = desc.charAt(c);
+ return n << 2
+ | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));
+ } else if (car == 'L') {
+ while (desc.charAt(c++) != ';') {
+ }
+ n += 1;
+ } else if (car == '[') {
+ while ((car = desc.charAt(c)) == '[') {
+ ++c;
+ }
+ if (car == 'D' || car == 'J') {
+ n -= 1;
+ }
+ } else if (car == 'D' || car == 'J') {
+ n += 2;
+ } else {
+ n += 1;
+ }
+ }
+ }
+
+ /**
+ * Returns the Java type corresponding to the given type descriptor. For
+ * method descriptors, buf is supposed to contain nothing more than the
+ * descriptor itself.
+ *
+ * @param buf
+ * a buffer containing a type descriptor.
+ * @param off
+ * the offset of this descriptor in the previous buffer.
+ * @return the Java type corresponding to the given type descriptor.
+ */
+ private static Type getType(final char[] buf, final int off) {
+ int len;
+ switch (buf[off]) {
+ case 'V':
+ return VOID_TYPE;
+ case 'Z':
+ return BOOLEAN_TYPE;
+ case 'C':
+ return CHAR_TYPE;
+ case 'B':
+ return BYTE_TYPE;
+ case 'S':
+ return SHORT_TYPE;
+ case 'I':
+ return INT_TYPE;
+ case 'F':
+ return FLOAT_TYPE;
+ case 'J':
+ return LONG_TYPE;
+ case 'D':
+ return DOUBLE_TYPE;
+ case '[':
+ len = 1;
+ while (buf[off + len] == '[') {
+ ++len;
+ }
+ if (buf[off + len] == 'L') {
+ ++len;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ }
+ return new Type(ARRAY, buf, off, len + 1);
+ case 'L':
+ len = 1;
+ while (buf[off + len] != ';') {
+ ++len;
+ }
+ return new Type(OBJECT, buf, off + 1, len - 1);
+ // case '(':
+ default:
+ return new Type(METHOD, buf, off, buf.length - off);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Accessors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the sort of this Java type.
+ *
+ * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},
+ * {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},
+ * {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},
+ * {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD
+ * METHOD}.
+ */
+ public int getSort() {
+ return sort;
+ }
+
+ /**
+ * Returns the number of dimensions of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return the number of dimensions of this array type.
+ */
+ public int getDimensions() {
+ int i = 1;
+ while (buf[off + i] == '[') {
+ ++i;
+ }
+ return i;
+ }
+
+ /**
+ * Returns the type of the elements of this array type. This method should
+ * only be used for an array type.
+ *
+ * @return Returns the type of the elements of this array type.
+ */
+ public Type getElementType() {
+ return getType(buf, off + getDimensions());
+ }
+
+ /**
+ * Returns the binary name of the class corresponding to this type. This
+ * method must not be used on method types.
+ *
+ * @return the binary name of the class corresponding to this type.
+ */
+ public String getClassName() {
+ switch (sort) {
+ case VOID:
+ return "void";
+ case BOOLEAN:
+ return "boolean";
+ case CHAR:
+ return "char";
+ case BYTE:
+ return "byte";
+ case SHORT:
+ return "short";
+ case INT:
+ return "int";
+ case FLOAT:
+ return "float";
+ case LONG:
+ return "long";
+ case DOUBLE:
+ return "double";
+ case ARRAY:
+ StringBuilder sb = new StringBuilder(getElementType().getClassName());
+ for (int i = getDimensions(); i > 0; --i) {
+ sb.append("[]");
+ }
+ return sb.toString();
+ case OBJECT:
+ return new String(buf, off, len).replace('/', '.');
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Returns the internal name of the class corresponding to this object or
+ * array type. The internal name of a class is its fully qualified name (as
+ * returned by Class.getName(), where '.' are replaced by '/'. This method
+ * should only be used for an object or array type.
+ *
+ * @return the internal name of the class corresponding to this object type.
+ */
+ public String getInternalName() {
+ return new String(buf, off, len);
+ }
+
+ /**
+ * Returns the argument types of methods of this type. This method should
+ * only be used for method types.
+ *
+ * @return the argument types of methods of this type.
+ */
+ public Type[] getArgumentTypes() {
+ return getArgumentTypes(getDescriptor());
+ }
+
+ /**
+ * Returns the return type of methods of this type. This method should only
+ * be used for method types.
+ *
+ * @return the return type of methods of this type.
+ */
+ public Type getReturnType() {
+ return getReturnType(getDescriptor());
+ }
+
+ /**
+ * Returns the size of the arguments and of the return value of methods of
+ * this type. This method should only be used for method types.
+ *
+ * @return the size of the arguments (plus one for the implicit this
+ * argument), argSize, and the size of the return value, retSize,
+ * packed into a single
+ * int i = <tt>(argSize << 2) | retSize</tt>
+ * (argSize is therefore equal to <tt>i >> 2</tt>,
+ * and retSize to <tt>i & 0x03</tt>).
+ */
+ public int getArgumentsAndReturnSizes() {
+ return getArgumentsAndReturnSizes(getDescriptor());
+ }
+
+ // ------------------------------------------------------------------------
+ // Conversion to type descriptors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the descriptor corresponding to this Java type.
+ *
+ * @return the descriptor corresponding to this Java type.
+ */
+ public String getDescriptor() {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given argument and return
+ * types.
+ *
+ * @param returnType
+ * the return type of the method.
+ * @param argumentTypes
+ * the argument types of the method.
+ * @return the descriptor corresponding to the given argument and return
+ * types.
+ */
+ public static String getMethodDescriptor(final Type returnType,
+ final Type... argumentTypes) {
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < argumentTypes.length; ++i) {
+ argumentTypes[i].getDescriptor(buf);
+ }
+ buf.append(')');
+ returnType.getDescriptor(buf);
+ return buf.toString();
+ }
+
+ /**
+ * Appends the descriptor corresponding to this Java type to the given
+ * string buffer.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
+ */
+ private void getDescriptor(final StringBuffer buf) {
+ if (this.buf == null) {
+ // descriptor is in byte 3 of 'off' for primitive types (buf ==
+ // null)
+ buf.append((char) ((off & 0xFF000000) >>> 24));
+ } else if (sort == OBJECT) {
+ buf.append('L');
+ buf.append(this.buf, off, len);
+ buf.append(';');
+ } else { // sort == ARRAY || sort == METHOD
+ buf.append(this.buf, off, len);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Direct conversion from classes to type descriptors,
+ // without intermediate Type objects
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the internal name of the given class. The internal name of a
+ * class is its fully qualified name, as returned by Class.getName(), where
+ * '.' are replaced by '/'.
+ *
+ * @param c
+ * an object or array class.
+ * @return the internal name of the given class.
+ */
+ public static String getInternalName(final Class<?> c) {
+ return c.getName().replace('.', '/');
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given Java type.
+ *
+ * @param c
+ * an object class, a primitive class or an array class.
+ * @return the descriptor corresponding to the given class.
+ */
+ public static String getDescriptor(final Class<?> c) {
+ StringBuffer buf = new StringBuffer();
+ getDescriptor(buf, c);
+ return buf.toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given constructor.
+ *
+ * @param c
+ * a {@link Constructor Constructor} object.
+ * @return the descriptor of the given constructor.
+ */
+ public static String getConstructorDescriptor(final Constructor<?> c) {
+ Class<?>[] parameters = c.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ return buf.append(")V").toString();
+ }
+
+ /**
+ * Returns the descriptor corresponding to the given method.
+ *
+ * @param m
+ * a {@link Method Method} object.
+ * @return the descriptor of the given method.
+ */
+ public static String getMethodDescriptor(final Method m) {
+ Class<?>[] parameters = m.getParameterTypes();
+ StringBuffer buf = new StringBuffer();
+ buf.append('(');
+ for (int i = 0; i < parameters.length; ++i) {
+ getDescriptor(buf, parameters[i]);
+ }
+ buf.append(')');
+ getDescriptor(buf, m.getReturnType());
+ return buf.toString();
+ }
+
+ /**
+ * Appends the descriptor of the given class to the given string buffer.
+ *
+ * @param buf
+ * the string buffer to which the descriptor must be appended.
+ * @param c
+ * the class whose descriptor must be computed.
+ */
+ private static void getDescriptor(final StringBuffer buf, final Class<?> c) {
+ Class<?> d = c;
+ while (true) {
+ if (d.isPrimitive()) {
+ char car;
+ if (d == Integer.TYPE) {
+ car = 'I';
+ } else if (d == Void.TYPE) {
+ car = 'V';
+ } else if (d == Boolean.TYPE) {
+ car = 'Z';
+ } else if (d == Byte.TYPE) {
+ car = 'B';
+ } else if (d == Character.TYPE) {
+ car = 'C';
+ } else if (d == Short.TYPE) {
+ car = 'S';
+ } else if (d == Double.TYPE) {
+ car = 'D';
+ } else if (d == Float.TYPE) {
+ car = 'F';
+ } else /* if (d == Long.TYPE) */{
+ car = 'J';
+ }
+ buf.append(car);
+ return;
+ } else if (d.isArray()) {
+ buf.append('[');
+ d = d.getComponentType();
+ } else {
+ buf.append('L');
+ String name = d.getName();
+ int len = name.length();
+ for (int i = 0; i < len; ++i) {
+ char car = name.charAt(i);
+ buf.append(car == '.' ? '/' : car);
+ }
+ buf.append(';');
+ return;
+ }
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Corresponding size and opcodes
+ // ------------------------------------------------------------------------
+
+ /**
+ * Returns the size of values of this type. This method must not be used for
+ * method types.
+ *
+ * @return the size of values of this type, i.e., 2 for <tt>long</tt> and
+ * <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.
+ */
+ public int getSize() {
+ // the size is in byte 0 of 'off' for primitive types (buf == null)
+ return buf == null ? (off & 0xFF) : 1;
+ }
+
+ /**
+ * Returns a JVM instruction opcode adapted to this Java type. This method
+ * must not be used for method types.
+ *
+ * @param opcode
+ * a JVM instruction opcode. This opcode must be one of ILOAD,
+ * ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,
+ * ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.
+ * @return an opcode that is similar to the given opcode, but adapted to
+ * this Java type. For example, if this type is <tt>float</tt> and
+ * <tt>opcode</tt> is IRETURN, this method returns FRETURN.
+ */
+ public int getOpcode(final int opcode) {
+ if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {
+ // the offset for IALOAD or IASTORE is in byte 1 of 'off' for
+ // primitive types (buf == null)
+ return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);
+ } else {
+ // the offset for other instructions is in byte 2 of 'off' for
+ // primitive types (buf == null)
+ return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Equals, hashCode and toString
+ // ------------------------------------------------------------------------
+
+ /**
+ * Tests if the given object is equal to this type.
+ *
+ * @param o
+ * the object to be compared to this type.
+ * @return <tt>true</tt> if the given object is equal to this type.
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof Type)) {
+ return false;
+ }
+ Type t = (Type) o;
+ if (sort != t.sort) {
+ return false;
+ }
+ if (sort >= ARRAY) {
+ if (len != t.len) {
+ return false;
+ }
+ for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {
+ if (buf[i] != t.buf[j]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns a hash code value for this type.
+ *
+ * @return a hash code value for this type.
+ */
+ @Override
+ public int hashCode() {
+ int hc = 13 * sort;
+ if (sort >= ARRAY) {
+ for (int i = off, end = i + len; i < end; i++) {
+ hc = 17 * (hc + buf[i]);
+ }
+ }
+ return hc;
+ }
+
+ /**
+ * Returns a string representation of this type.
+ *
+ * @return the descriptor of this type.
+ */
+ @Override
+ public String toString() {
+ return getDescriptor();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypePath.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypePath.java
new file mode 100644
index 0000000..62d3e93
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypePath.java
@@ -0,0 +1,196 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.powermock.objectweb.asm;
+
+/**
+ * The path to a type argument, wildcard bound, array element type, or static
+ * inner type within an enclosing type.
+ *
+ * @author Eric Bruneton
+ */
+public class TypePath {
+
+ /**
+ * A type path step that steps into the element type of an array type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int ARRAY_ELEMENT = 0;
+
+ /**
+ * A type path step that steps into the nested type of a class type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int INNER_TYPE = 1;
+
+ /**
+ * A type path step that steps into the bound of a wildcard type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int WILDCARD_BOUND = 2;
+
+ /**
+ * A type path step that steps into a type argument of a generic type. See
+ * {@link #getStep getStep}.
+ */
+ public final static int TYPE_ARGUMENT = 3;
+
+ /**
+ * The byte array where the path is stored, in Java class file format.
+ */
+ byte[] b;
+
+ /**
+ * The offset of the first byte of the type path in 'b'.
+ */
+ int offset;
+
+ /**
+ * Creates a new type path.
+ *
+ * @param b
+ * the byte array containing the type path in Java class file
+ * format.
+ * @param offset
+ * the offset of the first byte of the type path in 'b'.
+ */
+ TypePath(byte[] b, int offset) {
+ this.b = b;
+ this.offset = offset;
+ }
+
+ /**
+ * Returns the length of this path.
+ *
+ * @return the length of this path.
+ */
+ public int getLength() {
+ return b[offset];
+ }
+
+ /**
+ * Returns the value of the given step of this path.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE
+ * INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ */
+ public int getStep(int index) {
+ return b[offset + 2 * index + 1];
+ }
+
+ /**
+ * Returns the index of the type argument that the given step is stepping
+ * into. This method should only be used for steps whose value is
+ * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.
+ *
+ * @param index
+ * an index between 0 and {@link #getLength()}, exclusive.
+ * @return the index of the type argument that the given step is stepping
+ * into.
+ */
+ public int getStepArgument(int index) {
+ return b[offset + 2 * index + 2];
+ }
+
+ /**
+ * Converts a type path in string form, in the format used by
+ * {@link #toString()}, into a TypePath object.
+ *
+ * @param typePath
+ * a type path in string form, in the format used by
+ * {@link #toString()}. May be null or empty.
+ * @return the corresponding TypePath object, or null if the path is empty.
+ */
+ public static TypePath fromString(final String typePath) {
+ if (typePath == null || typePath.length() == 0) {
+ return null;
+ }
+ int n = typePath.length();
+ ByteVector out = new ByteVector(n);
+ out.putByte(0);
+ for (int i = 0; i < n;) {
+ char c = typePath.charAt(i++);
+ if (c == '[') {
+ out.put11(ARRAY_ELEMENT, 0);
+ } else if (c == '.') {
+ out.put11(INNER_TYPE, 0);
+ } else if (c == '*') {
+ out.put11(WILDCARD_BOUND, 0);
+ } else if (c >= '0' && c <= '9') {
+ int typeArg = c - '0';
+ while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {
+ typeArg = typeArg * 10 + c - '0';
+ i += 1;
+ }
+ if (i < n && typePath.charAt(i) == ';') {
+ i += 1;
+ }
+ out.put11(TYPE_ARGUMENT, typeArg);
+ }
+ }
+ out.data[0] = (byte) (out.length / 2);
+ return new TypePath(out.data, 0);
+ }
+
+ /**
+ * Returns a string representation of this type path. {@link #ARRAY_ELEMENT
+ * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE
+ * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps
+ * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type
+ * argument index in decimal form followed by ';'.
+ */
+ @Override
+ public String toString() {
+ int length = getLength();
+ StringBuilder result = new StringBuilder(length * 2);
+ for (int i = 0; i < length; ++i) {
+ switch (getStep(i)) {
+ case ARRAY_ELEMENT:
+ result.append('[');
+ break;
+ case INNER_TYPE:
+ result.append('.');
+ break;
+ case WILDCARD_BOUND:
+ result.append('*');
+ break;
+ case TYPE_ARGUMENT:
+ result.append(getStepArgument(i)).append(';');
+ break;
+ default:
+ result.append('_');
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypeReference.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypeReference.java
new file mode 100644
index 0000000..23e78be
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/TypeReference.java
@@ -0,0 +1,452 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.powermock.objectweb.asm;
+
+/**
+ * A reference to a type appearing in a class, field or method declaration, or
+ * on an instruction. Such a reference designates the part of the class where
+ * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'
+ * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable
+ * declaration, etc).
+ *
+ * @author Eric Bruneton
+ */
+public class TypeReference {
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER = 0x00;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER = 0x01;
+
+ /**
+ * The sort of type references that target the super class of a class or one
+ * of the interfaces it implements. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_EXTENDS = 0x10;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic class. See {@link #getSort getSort}.
+ */
+ public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;
+
+ /**
+ * The sort of type references that target a bound of a type parameter of a
+ * generic method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;
+
+ /**
+ * The sort of type references that target the type of a field. See
+ * {@link #getSort getSort}.
+ */
+ public final static int FIELD = 0x13;
+
+ /**
+ * The sort of type references that target the return type of a method. See
+ * {@link #getSort getSort}.
+ */
+ public final static int METHOD_RETURN = 0x14;
+
+ /**
+ * The sort of type references that target the receiver type of a method.
+ * See {@link #getSort getSort}.
+ */
+ public final static int METHOD_RECEIVER = 0x15;
+
+ /**
+ * The sort of type references that target the type of a formal parameter of
+ * a method. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_FORMAL_PARAMETER = 0x16;
+
+ /**
+ * The sort of type references that target the type of an exception declared
+ * in the throws clause of a method. See {@link #getSort getSort}.
+ */
+ public final static int THROWS = 0x17;
+
+ /**
+ * The sort of type references that target the type of a local variable in a
+ * method. See {@link #getSort getSort}.
+ */
+ public final static int LOCAL_VARIABLE = 0x40;
+
+ /**
+ * The sort of type references that target the type of a resource variable
+ * in a method. See {@link #getSort getSort}.
+ */
+ public final static int RESOURCE_VARIABLE = 0x41;
+
+ /**
+ * The sort of type references that target the type of the exception of a
+ * 'catch' clause in a method. See {@link #getSort getSort}.
+ */
+ public final static int EXCEPTION_PARAMETER = 0x42;
+
+ /**
+ * The sort of type references that target the type declared in an
+ * 'instanceof' instruction. See {@link #getSort getSort}.
+ */
+ public final static int INSTANCEOF = 0x43;
+
+ /**
+ * The sort of type references that target the type of the object created by
+ * a 'new' instruction. See {@link #getSort getSort}.
+ */
+ public final static int NEW = 0x44;
+
+ /**
+ * The sort of type references that target the receiver type of a
+ * constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE = 0x45;
+
+ /**
+ * The sort of type references that target the receiver type of a method
+ * reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE = 0x46;
+
+ /**
+ * The sort of type references that target the type declared in an explicit
+ * or implicit cast instruction. See {@link #getSort getSort}.
+ */
+ public final static int CAST = 0x47;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor call. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method call. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * constructor in a constructor reference. See {@link #getSort getSort}.
+ */
+ public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;
+
+ /**
+ * The sort of type references that target a type parameter of a generic
+ * method in a method reference. See {@link #getSort getSort}.
+ */
+ public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;
+
+ /**
+ * The type reference value in Java class file format.
+ */
+ private int value;
+
+ /**
+ * Creates a new TypeReference.
+ *
+ * @param typeRef
+ * the int encoded value of the type reference, as received in a
+ * visit method related to type annotations, like
+ * visitTypeAnnotation.
+ */
+ public TypeReference(int typeRef) {
+ this.value = typeRef;
+ }
+
+ /**
+ * Returns a type reference of the given sort.
+ *
+ * @param sort
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}.
+ * @return a type reference of the given sort.
+ */
+ public static TypeReference newTypeReference(int sort) {
+ return new TypeReference(sort << 24);
+ }
+
+ /**
+ * Returns a reference to a type parameter of a generic class or method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @return a reference to the given generic class or method type parameter.
+ */
+ public static TypeReference newTypeParameterReference(int sort,
+ int paramIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to a type parameter bound of a generic class or
+ * method.
+ *
+ * @param sort
+ * {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.
+ * @param paramIndex
+ * the type parameter index.
+ * @param boundIndex
+ * the type bound index within the above type parameters.
+ * @return a reference to the given generic class or method type parameter
+ * bound.
+ */
+ public static TypeReference newTypeParameterBoundReference(int sort,
+ int paramIndex, int boundIndex) {
+ return new TypeReference((sort << 24) | (paramIndex << 16)
+ | (boundIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the super class or to an interface of the
+ * 'implements' clause of a class.
+ *
+ * @param itfIndex
+ * the index of an interface in the 'implements' clause of a
+ * class, or -1 to reference the super class of the class.
+ * @return a reference to the given super type of a class.
+ */
+ public static TypeReference newSuperTypeReference(int itfIndex) {
+ itfIndex &= 0xFFFF;
+ return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a formal parameter of a method.
+ *
+ * @param paramIndex
+ * the formal parameter index.
+ *
+ * @return a reference to the type of the given method formal parameter.
+ */
+ public static TypeReference newFormalParameterReference(int paramIndex) {
+ return new TypeReference((METHOD_FORMAL_PARAMETER << 24)
+ | (paramIndex << 16));
+ }
+
+ /**
+ * Returns a reference to the type of an exception, in a 'throws' clause of
+ * a method.
+ *
+ * @param exceptionIndex
+ * the index of an exception in a 'throws' clause of a method.
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newExceptionReference(int exceptionIndex) {
+ return new TypeReference((THROWS << 24) | (exceptionIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of the exception declared in a 'catch'
+ * clause of a method.
+ *
+ * @param tryCatchBlockIndex
+ * the index of a try catch block (using the order in which they
+ * are visited with visitTryCatchBlock).
+ *
+ * @return a reference to the type of the given exception.
+ */
+ public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {
+ return new TypeReference((EXCEPTION_PARAMETER << 24)
+ | (tryCatchBlockIndex << 8));
+ }
+
+ /**
+ * Returns a reference to the type of a type argument in a constructor or
+ * method call or reference.
+ *
+ * @param sort
+ * {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ * @param argIndex
+ * the type argument index.
+ *
+ * @return a reference to the type of the given type argument.
+ */
+ public static TypeReference newTypeArgumentReference(int sort, int argIndex) {
+ return new TypeReference((sort << 24) | argIndex);
+ }
+
+ /**
+ * Returns the sort of this type reference.
+ *
+ * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_EXTENDS CLASS_EXTENDS},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},
+ * {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},
+ * {@link #METHOD_RECEIVER METHOD_RECEIVER},
+ * {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},
+ * {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},
+ * {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},
+ * {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},
+ * {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},
+ * {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},
+ * {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},
+ * {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT
+ * METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT
+ * METHOD_REFERENCE_TYPE_ARGUMENT}.
+ */
+ public int getSort() {
+ return value >>> 24;
+ }
+
+ /**
+ * Returns the index of the type parameter referenced by this type
+ * reference. This method must only be used for type references whose sort
+ * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},
+ * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the type parameter bound, within the type parameter
+ * {@link #getTypeParameterIndex}, referenced by this type reference. This
+ * method must only be used for type references whose sort is
+ * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or
+ * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.
+ *
+ * @return a type parameter bound index.
+ */
+ public int getTypeParameterBoundIndex() {
+ return (value & 0x0000FF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the "super type" of a class that is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.
+ *
+ * @return the index of an interface in the 'implements' clause of a class,
+ * or -1 if this type reference references the type of the super
+ * class.
+ */
+ public int getSuperTypeIndex() {
+ return (short) ((value & 0x00FFFF00) >> 8);
+ }
+
+ /**
+ * Returns the index of the formal parameter whose type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.
+ *
+ * @return a formal parameter index.
+ */
+ public int getFormalParameterIndex() {
+ return (value & 0x00FF0000) >> 16;
+ }
+
+ /**
+ * Returns the index of the exception, in a 'throws' clause of a method,
+ * whose type is referenced by this type reference. This method must only be
+ * used for type references whose sort is {@link #THROWS THROWS}.
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getExceptionIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the try catch block (using the order in which they
+ * are visited with visitTryCatchBlock), whose 'catch' type is referenced by
+ * this type reference. This method must only be used for type references
+ * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .
+ *
+ * @return the index of an exception in the 'throws' clause of a method.
+ */
+ public int getTryCatchBlockIndex() {
+ return (value & 0x00FFFF00) >> 8;
+ }
+
+ /**
+ * Returns the index of the type argument referenced by this type reference.
+ * This method must only be used for type references whose sort is
+ * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT
+ * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},
+ * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},
+ * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT
+ * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or
+ * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.
+ *
+ * @return a type parameter index.
+ */
+ public int getTypeArgumentIndex() {
+ return value & 0xFF;
+ }
+
+ /**
+ * Returns the int encoded value of this type reference, suitable for use in
+ * visit methods related to type annotations, like visitTypeAnnotation.
+ *
+ * @return the int encoded value of this type reference.
+ */
+ public int getValue() {
+ return value;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/package-info.java b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/package-info.java
new file mode 100644
index 0000000..2274c45
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/org/powermock/objectweb/asm/package-info.java
@@ -0,0 +1,34 @@
+/*
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * Repackaged from ASM 5.0.4
+ */
+package org.powermock.objectweb.asm;
\ No newline at end of file
diff --git a/modules/module-impl/agent/src/main/java/sun/tools/attach/BsdVirtualMachine.java b/modules/module-impl/agent/src/main/java/sun/tools/attach/BsdVirtualMachine.java
new file mode 100644
index 0000000..3c2b535
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/sun/tools/attach/BsdVirtualMachine.java
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.tools.attach;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.spi.AttachProvider;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.File;
+import java.util.Properties;
+
+/*
+ * Bsd implementation of HotSpotVirtualMachine
+ */
+public class BsdVirtualMachine extends HotSpotVirtualMachine {
+ // "tmpdir" is used as a global well-known location for the files
+ // .java_pid<pid>. and .attach_pid<pid>. It is important that this
+ // location is the same for all processes, otherwise the tools
+ // will not be able to find all Hotspot processes.
+ // This is intentionally not the same as java.io.tmpdir, since
+ // the latter can be changed by the user.
+ // Any changes to this needs to be synchronized with HotSpot.
+ private static final String tmpdir;
+
+ // The patch to the socket file created by the target VM
+ String path;
+
+ /**
+ * Attaches to the target VM
+ */
+ public BsdVirtualMachine(AttachProvider provider, String vmid)
+ throws AttachNotSupportedException, IOException
+ {
+ super(provider, vmid);
+
+ // This provider only understands pids
+ int pid;
+ try {
+ pid = Integer.parseInt(vmid);
+ } catch (NumberFormatException x) {
+ throw new AttachNotSupportedException("Invalid process identifier");
+ }
+
+ // Find the socket file. If not found then we attempt to start the
+ // attach mechanism in the target VM by sending it a QUIT signal.
+ // Then we attempt to find the socket file again.
+ path = findSocketFile(pid);
+ if (path == null) {
+ File f = new File(tmpdir, ".attach_pid" + pid);
+ createAttachFile(f.getPath());
+ try {
+ sendQuitTo(pid);
+
+ // give the target VM time to start the attach mechanism
+ int i = 0;
+ long delay = 200;
+ int retries = (int)(attachTimeout() / delay);
+ do {
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException x) { }
+ path = findSocketFile(pid);
+ i++;
+ } while (i <= retries && path == null);
+ if (path == null) {
+ throw new AttachNotSupportedException(
+ "Unable to open socket file: target process not responding " +
+ "or HotSpot VM not loaded");
+ }
+ } finally {
+ f.delete();
+ }
+ }
+
+ // Check that the file owner/permission to avoid attaching to
+ // bogus process
+ checkPermissions(path);
+
+ // Check that we can connect to the process
+ // - this ensures we throw the permission denied error now rather than
+ // later when we attempt to enqueue a command.
+ int s = socket();
+ try {
+ connect(s, path);
+ } finally {
+ close(s);
+ }
+ }
+
+ /**
+ * Detach from the target VM
+ */
+ @Override
+ public void detach() throws IOException {
+ synchronized (this) {
+ if (this.path != null) {
+ this.path = null;
+ }
+ }
+ }
+
+ // protocol version
+ private final static String PROTOCOL_VERSION = "1";
+
+ // known errors
+ private final static int ATTACH_ERROR_BADVERSION = 101;
+
+ /**
+ * Execute the given command in the target VM.
+ */
+ @Override
+ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
+ assert args.length <= 3; // includes null
+
+ // did we detach?
+ String p;
+ synchronized (this) {
+ if (this.path == null) {
+ throw new IOException("Detached from target VM");
+ }
+ p = this.path;
+ }
+
+ // create UNIX socket
+ int s = socket();
+
+ // connect to target VM
+ try {
+ connect(s, p);
+ } catch (IOException x) {
+ close(s);
+ throw x;
+ }
+
+ IOException ioe = null;
+
+ // connected - write request
+ // <ver> <cmd> <args...>
+ try {
+ writeString(s, PROTOCOL_VERSION);
+ writeString(s, cmd);
+
+ for (int i=0; i<3; i++) {
+ if (i < args.length && args[i] != null) {
+ writeString(s, (String)args[i]);
+ } else {
+ writeString(s, "");
+ }
+ }
+ } catch (IOException x) {
+ ioe = x;
+ }
+
+
+ // Create an input stream to read reply
+ SocketInputStream sis = new SocketInputStream(s);
+
+ // Read the command completion status
+ int completionStatus;
+ try {
+ completionStatus = readInt(sis);
+ } catch (IOException x) {
+ sis.close();
+ if (ioe != null) {
+ throw ioe;
+ } else {
+ throw x;
+ }
+ }
+
+ if (completionStatus != 0) {
+ sis.close();
+
+ // In the event of a protocol mismatch then the target VM
+ // returns a known error so that we can throw a reasonable
+ // error.
+ if (completionStatus == ATTACH_ERROR_BADVERSION) {
+ throw new IOException("Protocol mismatch with target VM");
+ }
+
+ // Special-case the "load" command so that the right exception is
+ // thrown.
+ if (cmd.equals("load")) {
+ throw new AgentLoadException("Failed to load agent library");
+ } else {
+ throw new IOException("Command failed in target VM");
+ }
+ }
+
+ // Return the input stream so that the command output can be read
+ return sis;
+ }
+
+ /*
+ * InputStream for the socket connection to get target VM
+ */
+ private class SocketInputStream extends InputStream {
+ int s;
+
+ public SocketInputStream(int s) {
+ this.s = s;
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = this.read(b, 0, 1);
+ if (n == 1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public synchronized int read(byte[] bs, int off, int len) throws IOException {
+ if ((off < 0) || (off > bs.length) || (len < 0) ||
+ ((off + len) > bs.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0)
+ return 0;
+
+ return BsdVirtualMachine.read(s, bs, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ BsdVirtualMachine.close(s);
+ }
+ }
+
+ // Return the socket file for the given process.
+ // Checks temp directory for .java_pid<pid>.
+ private String findSocketFile(int pid) {
+ String fn = ".java_pid" + pid;
+ File f = new File(tmpdir, fn);
+ return f.exists() ? f.getPath() : null;
+ }
+
+ /*
+ * Write/sends the given to the target VM. String is transmitted in
+ * UTF-8 encoding.
+ */
+ private void writeString(int fd, String s) throws IOException {
+ if (s.length() > 0) {
+ byte b[];
+ try {
+ b = s.getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException x) {
+ throw new InternalError();
+ }
+ BsdVirtualMachine.write(fd, b, 0, b.length);
+ }
+ byte b[] = new byte[1];
+ b[0] = 0;
+ write(fd, b, 0, 1);
+ }
+
+
+ //-- native methods
+
+ static native void sendQuitTo(int pid) throws IOException;
+
+ static native void checkPermissions(String path) throws IOException;
+
+ static native int socket() throws IOException;
+
+ static native void connect(int fd, String path) throws IOException;
+
+ static native void close(int fd) throws IOException;
+
+ static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
+
+ static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
+
+ static native void createAttachFile(String path);
+
+ static native String getTempDir();
+
+ static {
+ System.loadLibrary("attach");
+ tmpdir = getTempDir();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/sun/tools/attach/HotSpotVirtualMachine.java b/modules/module-impl/agent/src/main/java/sun/tools/attach/HotSpotVirtualMachine.java
new file mode 100644
index 0000000..a6b9b93
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/sun/tools/attach/HotSpotVirtualMachine.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package sun.tools.attach;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AgentInitializationException;
+import com.sun.tools.attach.spi.AttachProvider;
+
+import java.io.InputStream;
+import java.io.IOException;
+import java.util.Properties;
+import java.util.Map;
+
+/*
+ * The HotSpot implementation of com.sun.tools.attach.VirtualMachine.
+ */
+
+public abstract class HotSpotVirtualMachine extends VirtualMachine {
+
+ HotSpotVirtualMachine(AttachProvider provider, String id) {
+ super(provider, id);
+ }
+
+ /*
+ * Load agent library
+ * If isAbsolute is true then the agent library is the absolute path
+ * to the library and thus will not be expanded in the target VM.
+ * if isAbsolute is false then the agent library is just a library
+ * name and it will be expended in the target VM.
+ */
+ private void loadAgentLibrary(String agentLibrary, boolean isAbsolute, String options)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ InputStream in = execute("load",
+ agentLibrary,
+ isAbsolute ? "true" : "false",
+ options);
+ try {
+ int result = readInt(in);
+ if (result != 0) {
+ throw new AgentInitializationException("Agent_OnAttach failed", result);
+ }
+ } finally {
+ in.close();
+
+ }
+ }
+
+ /*
+ * Load agent library - library name will be expanded in target VM
+ */
+ @Override
+ public void loadAgentLibrary(String agentLibrary, String options)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ loadAgentLibrary(agentLibrary, false, options);
+ }
+
+ /*
+ * Load agent - absolute path of library provided to target VM
+ */
+ @Override
+ public void loadAgentPath(String agentLibrary, String options)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ loadAgentLibrary(agentLibrary, true, options);
+ }
+
+ /*
+ * Load JPLIS agent which will load the agent JAR file and invoke
+ * the agentmain method.
+ */
+ @Override
+ public void loadAgent(String agent, String options)
+ throws AgentLoadException, AgentInitializationException, IOException
+ {
+ String args = agent;
+ if (options != null) {
+ args = args + "=" + options;
+ }
+ try {
+ loadAgentLibrary("instrument", args);
+ } catch (AgentLoadException x) {
+ throw new InternalError("instrument library is missing in target VM");
+ } catch (AgentInitializationException x) {
+ /*
+ * Translate interesting errors into the right exception and
+ * message (FIXME: create a better interface to the instrument
+ * implementation so this isn't necessary)
+ */
+ int rc = x.returnValue();
+ switch (rc) {
+ case JNI_ENOMEM:
+ throw new AgentLoadException("Insuffient memory");
+ case ATTACH_ERROR_BADJAR:
+ throw new AgentLoadException("Agent JAR not found or no Agent-Class attribute");
+ case ATTACH_ERROR_NOTONCP:
+ throw new AgentLoadException("Unable to add JAR file to system class path");
+ case ATTACH_ERROR_STARTFAIL:
+ throw new AgentInitializationException("Agent JAR loaded but agent failed to initialize");
+ default :
+ throw new AgentLoadException("Failed to load agent - unknown reason: " + rc);
+ }
+ }
+ }
+
+ /*
+ * The possible errors returned by JPLIS's agentmain
+ */
+ private static final int JNI_ENOMEM = -4;
+ private static final int ATTACH_ERROR_BADJAR = 100;
+ private static final int ATTACH_ERROR_NOTONCP = 101;
+ private static final int ATTACH_ERROR_STARTFAIL = 102;
+
+
+ /*
+ * Send "properties" command to target VM
+ */
+ @Override
+ public Properties getSystemProperties() throws IOException {
+ InputStream in = null;
+ Properties props = new Properties();
+ try {
+ in = executeCommand("properties");
+ props.load(in);
+ } finally {
+ if (in != null) in.close();
+ }
+ return props;
+ }
+
+ @Override
+ public Properties getAgentProperties() throws IOException {
+ InputStream in = null;
+ Properties props = new Properties();
+ try {
+ in = executeCommand("agentProperties");
+ props.load(in);
+ } finally {
+ if (in != null) in.close();
+ }
+ return props;
+ }
+
+ // --- HotSpot specific methods ---
+
+ // same as SIGQUIT
+ public void localDataDump() throws IOException {
+ executeCommand("datadump").close();
+ }
+
+ // Remote ctrl-break. The output of the ctrl-break actions can
+ // be read from the input stream.
+ public InputStream remoteDataDump(Object ... args) throws IOException {
+ return executeCommand("threaddump", args);
+ }
+
+ // Remote heap dump. The output (error message) can be read from the
+ // returned input stream.
+ public InputStream dumpHeap(Object ... args) throws IOException {
+ return executeCommand("dumpheap", args);
+ }
+
+ // Heap histogram (heap inspection in HotSpot)
+ public InputStream heapHisto(Object ... args) throws IOException {
+ return executeCommand("inspectheap", args);
+ }
+
+ // set JVM command line flag
+ public InputStream setFlag(String name, String value) throws IOException {
+ return executeCommand("setflag", name, value);
+ }
+
+ // print command line flag
+ public InputStream printFlag(String name) throws IOException {
+ return executeCommand("printflag", name);
+ }
+
+ public InputStream executeJCmd(String command) throws IOException {
+ return executeCommand("jcmd", command);
+ }
+
+ // -- Supporting methods
+
+
+ /*
+ * Execute the given command in the target VM - specific platform
+ * implementation must implement this.
+ */
+ abstract InputStream execute(String cmd, Object ... args)
+ throws AgentLoadException, IOException;
+
+ /*
+ * Convenience method for simple commands
+ */
+ private InputStream executeCommand(String cmd, Object ... args) throws IOException {
+ try {
+ return execute(cmd, args);
+ } catch (AgentLoadException x) {
+ throw new InternalError("Should not get here");
+ }
+ }
+
+
+ /*
+ * Utility method to read an 'int' from the input stream. Ideally
+ * we should be using java.util.Scanner here but this implementation
+ * guarantees not to read ahead.
+ */
+ int readInt(InputStream in) throws IOException {
+ StringBuilder sb = new StringBuilder();
+
+ // read to \n or EOF
+ int n;
+ byte buf[] = new byte[1];
+ do {
+ n = in.read(buf, 0, 1);
+ if (n > 0) {
+ char c = (char)buf[0];
+ if (c == '\n') {
+ break; // EOL found
+ } else {
+ sb.append(c);
+ }
+ }
+ } while (n > 0);
+
+ if (sb.length() == 0) {
+ throw new IOException("Premature EOF");
+ }
+
+ int value;
+ try {
+ value = Integer.parseInt(sb.toString());
+ } catch (NumberFormatException x) {
+ throw new IOException("Non-numeric value found - int expected");
+ }
+ return value;
+ }
+
+ // -- attach timeout support
+
+ private static long defaultAttachTimeout = 5000;
+ private volatile long attachTimeout;
+
+ /*
+ * Return attach timeout based on the value of the sun.tools.attach.attachTimeout
+ * property, or the default timeout if the property is not set to a positive
+ * value.
+ */
+ final long attachTimeout() {
+ if (attachTimeout == 0) {
+ synchronized(this) {
+ if (attachTimeout == 0) {
+ try {
+ String s =
+ System.getProperty("sun.tools.attach.attachTimeout");
+ attachTimeout = Long.parseLong(s);
+ } catch (SecurityException se) {
+ } catch (NumberFormatException ne) {
+ }
+ if (attachTimeout <= 0) {
+ attachTimeout = defaultAttachTimeout;
+ }
+ }
+ }
+ }
+ return attachTimeout;
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/sun/tools/attach/LinuxVirtualMachine.java b/modules/module-impl/agent/src/main/java/sun/tools/attach/LinuxVirtualMachine.java
new file mode 100644
index 0000000..da14298
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/sun/tools/attach/LinuxVirtualMachine.java
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.tools.attach;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.spi.AttachProvider;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.File;
+import java.util.Properties;
+
+/*
+ * Linux implementation of HotSpotVirtualMachine
+ */
+public class LinuxVirtualMachine extends HotSpotVirtualMachine {
+ // "/tmp" is used as a global well-known location for the files
+ // .java_pid<pid>. and .attach_pid<pid>. It is important that this
+ // location is the same for all processes, otherwise the tools
+ // will not be able to find all Hotspot processes.
+ // Any changes to this needs to be synchronized with HotSpot.
+ private static final String tmpdir = "/tmp";
+
+ // Indicates if this machine uses the old LinuxThreads
+ static boolean isLinuxThreads;
+
+ // The patch to the socket file created by the target VM
+ String path;
+
+ /**
+ * Attaches to the target VM
+ */
+ public LinuxVirtualMachine(AttachProvider provider, String vmid)
+ throws AttachNotSupportedException, IOException
+ {
+ super(provider, vmid);
+
+ // This provider only understands pids
+ int pid;
+ try {
+ pid = Integer.parseInt(vmid);
+ } catch (NumberFormatException x) {
+ throw new AttachNotSupportedException("Invalid process identifier");
+ }
+
+ // Find the socket file. If not found then we attempt to start the
+ // attach mechanism in the target VM by sending it a QUIT signal.
+ // Then we attempt to find the socket file again.
+ path = findSocketFile(pid);
+ if (path == null) {
+ File f = createAttachFile(pid);
+ try {
+ // On LinuxThreads each thread is a process and we don't have the
+ // pid of the VMThread which has SIGQUIT unblocked. To workaround
+ // this we get the pid of the "manager thread" that is created
+ // by the first call to pthread_create. This is parent of all
+ // threads (except the initial thread).
+ if (isLinuxThreads) {
+ int mpid;
+ try {
+ mpid = getLinuxThreadsManager(pid);
+ } catch (IOException x) {
+ throw new AttachNotSupportedException(x.getMessage());
+ }
+ assert(mpid >= 1);
+ sendQuitToChildrenOf(mpid);
+ } else {
+ sendQuitTo(pid);
+ }
+
+ // give the target VM time to start the attach mechanism
+ int i = 0;
+ long delay = 200;
+ int retries = (int)(attachTimeout() / delay);
+ do {
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException x) { }
+ path = findSocketFile(pid);
+ i++;
+ } while (i <= retries && path == null);
+ if (path == null) {
+ throw new AttachNotSupportedException(
+ "Unable to open socket file: target process not responding " +
+ "or HotSpot VM not loaded");
+ }
+ } finally {
+ f.delete();
+ }
+ }
+
+ // Check that the file owner/permission to avoid attaching to
+ // bogus process
+ checkPermissions(path);
+
+ // Check that we can connect to the process
+ // - this ensures we throw the permission denied error now rather than
+ // later when we attempt to enqueue a command.
+ int s = socket();
+ try {
+ connect(s, path);
+ } finally {
+ close(s);
+ }
+ }
+
+ /**
+ * Detach from the target VM
+ */
+ @Override
+ public void detach() throws IOException {
+ synchronized (this) {
+ if (this.path != null) {
+ this.path = null;
+ }
+ }
+ }
+
+ // protocol version
+ private final static String PROTOCOL_VERSION = "1";
+
+ // known errors
+ private final static int ATTACH_ERROR_BADVERSION = 101;
+
+ /**
+ * Execute the given command in the target VM.
+ */
+ @Override
+ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
+ assert args.length <= 3; // includes null
+
+ // did we detach?
+ String p;
+ synchronized (this) {
+ if (this.path == null) {
+ throw new IOException("Detached from target VM");
+ }
+ p = this.path;
+ }
+
+ // create UNIX socket
+ int s = socket();
+
+ // connect to target VM
+ try {
+ connect(s, p);
+ } catch (IOException x) {
+ close(s);
+ throw x;
+ }
+
+ IOException ioe = null;
+
+ // connected - write request
+ // <ver> <cmd> <args...>
+ try {
+ writeString(s, PROTOCOL_VERSION);
+ writeString(s, cmd);
+
+ for (int i=0; i<3; i++) {
+ if (i < args.length && args[i] != null) {
+ writeString(s, (String)args[i]);
+ } else {
+ writeString(s, "");
+ }
+ }
+ } catch (IOException x) {
+ ioe = x;
+ }
+
+
+ // Create an input stream to read reply
+ SocketInputStream sis = new SocketInputStream(s);
+
+ // Read the command completion status
+ int completionStatus;
+ try {
+ completionStatus = readInt(sis);
+ } catch (IOException x) {
+ sis.close();
+ if (ioe != null) {
+ throw ioe;
+ } else {
+ throw x;
+ }
+ }
+
+ if (completionStatus != 0) {
+ sis.close();
+
+ // In the event of a protocol mismatch then the target VM
+ // returns a known error so that we can throw a reasonable
+ // error.
+ if (completionStatus == ATTACH_ERROR_BADVERSION) {
+ throw new IOException("Protocol mismatch with target VM");
+ }
+
+ // Special-case the "load" command so that the right exception is
+ // thrown.
+ if (cmd.equals("load")) {
+ throw new AgentLoadException("Failed to load agent library");
+ } else {
+ throw new IOException("Command failed in target VM");
+ }
+ }
+
+ // Return the input stream so that the command output can be read
+ return sis;
+ }
+
+ /*
+ * InputStream for the socket connection to get target VM
+ */
+ private class SocketInputStream extends InputStream {
+ int s;
+
+ public SocketInputStream(int s) {
+ this.s = s;
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = this.read(b, 0, 1);
+ if (n == 1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public synchronized int read(byte[] bs, int off, int len) throws IOException {
+ if ((off < 0) || (off > bs.length) || (len < 0) ||
+ ((off + len) > bs.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0)
+ return 0;
+
+ return LinuxVirtualMachine.read(s, bs, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ LinuxVirtualMachine.close(s);
+ }
+ }
+
+ // Return the socket file for the given process.
+ private String findSocketFile(int pid) {
+ File f = new File(tmpdir, ".java_pid" + pid);
+ if (!f.exists()) {
+ return null;
+ }
+ return f.getPath();
+ }
+
+ // On Solaris/Linux a simple handshake is used to start the attach mechanism
+ // if not already started. The client creates a .attach_pid<pid> file in the
+ // target VM's working directory (or temp directory), and the SIGQUIT handler
+ // checks for the file.
+ private File createAttachFile(int pid) throws IOException {
+ String fn = ".attach_pid" + pid;
+ String path = "/proc/" + pid + "/cwd/" + fn;
+ File f = new File(path);
+ try {
+ f.createNewFile();
+ } catch (IOException x) {
+ f = new File(tmpdir, fn);
+ f.createNewFile();
+ }
+ return f;
+ }
+
+ /*
+ * Write/sends the given to the target VM. String is transmitted in
+ * UTF-8 encoding.
+ */
+ private void writeString(int fd, String s) throws IOException {
+ if (s.length() > 0) {
+ byte b[];
+ try {
+ b = s.getBytes("UTF-8");
+ } catch (java.io.UnsupportedEncodingException x) {
+ throw new InternalError();
+ }
+ LinuxVirtualMachine.write(fd, b, 0, b.length);
+ }
+ byte b[] = new byte[1];
+ b[0] = 0;
+ write(fd, b, 0, 1);
+ }
+
+
+ //-- native methods
+
+ static native boolean isLinuxThreads();
+
+ static native int getLinuxThreadsManager(int pid) throws IOException;
+
+ static native void sendQuitToChildrenOf(int pid) throws IOException;
+
+ static native void sendQuitTo(int pid) throws IOException;
+
+ static native void checkPermissions(String path) throws IOException;
+
+ static native int socket() throws IOException;
+
+ static native void connect(int fd, String path) throws IOException;
+
+ static native void close(int fd) throws IOException;
+
+ static native int read(int fd, byte buf[], int off, int bufLen) throws IOException;
+
+ static native void write(int fd, byte buf[], int off, int bufLen) throws IOException;
+
+ static {
+ System.loadLibrary("attach");
+ isLinuxThreads = isLinuxThreads();
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/sun/tools/attach/SolarisVirtualMachine.java b/modules/module-impl/agent/src/main/java/sun/tools/attach/SolarisVirtualMachine.java
new file mode 100644
index 0000000..67384d0
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/sun/tools/attach/SolarisVirtualMachine.java
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.tools.attach;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.spi.AttachProvider;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.Properties;
+
+/*
+ * Solaris implementation of HotSpotVirtualMachine.
+ */
+public class SolarisVirtualMachine extends HotSpotVirtualMachine {
+ // "/tmp" is used as a global well-known location for the files
+ // .java_pid<pid>. and .attach_pid<pid>. It is important that this
+ // location is the same for all processes, otherwise the tools
+ // will not be able to find all Hotspot processes.
+ // Any changes to this needs to be synchronized with HotSpot.
+ private static final String tmpdir = "/tmp";
+
+ // door descriptor;
+ private int fd = -1;
+
+ /**
+ * Attaches to the target VM
+ */
+ public SolarisVirtualMachine(AttachProvider provider, String vmid)
+ throws AttachNotSupportedException, IOException
+ {
+ super(provider, vmid);
+ // This provider only understands process-ids (pids).
+ int pid;
+ try {
+ pid = Integer.parseInt(vmid);
+ } catch (NumberFormatException x) {
+ throw new AttachNotSupportedException("invalid process identifier");
+ }
+
+ // Opens the door file to the target VM. If the file is not
+ // found it might mean that the attach mechanism isn't started in the
+ // target VM so we attempt to start it and retry.
+ try {
+ fd = openDoor(pid);
+ } catch (FileNotFoundException fnf1) {
+ File f = createAttachFile(pid);
+ try {
+ // kill -QUIT will tickle target VM to check for the
+ // attach file.
+ sigquit(pid);
+
+ // give the target VM time to start the attach mechanism
+ int i = 0;
+ long delay = 200;
+ int retries = (int)(attachTimeout() / delay);
+ do {
+ try {
+ Thread.sleep(delay);
+ } catch (InterruptedException x) { }
+ try {
+ fd = openDoor(pid);
+ } catch (FileNotFoundException fnf2) { }
+ i++;
+ } while (i <= retries && fd == -1);
+ if (fd == -1) {
+ throw new AttachNotSupportedException(
+ "Unable to open door: target process not responding or " +
+ "HotSpot VM not loaded");
+ }
+ } finally {
+ f.delete();
+ }
+ }
+ assert fd >= 0;
+ }
+
+ /**
+ * Detach from the target VM
+ */
+ @Override
+ public void detach() throws IOException {
+ synchronized (this) {
+ if (fd != -1) {
+ close(fd);
+ fd = -1;
+ }
+ }
+ }
+
+ /**
+ * Execute the given command in the target VM.
+ */
+ @Override
+ InputStream execute(String cmd, Object ... args) throws AgentLoadException, IOException {
+ assert args.length <= 3; // includes null
+
+ // first check that we are still attached
+ int door;
+ synchronized (this) {
+ if (fd == -1) {
+ throw new IOException("Detached from target VM");
+ }
+ door = fd;
+ }
+
+ // enqueue the command via a door call
+ int s = enqueue(door, cmd, args);
+ assert s >= 0; // valid file descriptor
+
+ // The door call returns a file descriptor (one end of a socket pair).
+ // Create an input stream around it.
+ SocketInputStream sis = new SocketInputStream(s);
+
+ // Read the command completion status
+ int completionStatus;
+ try {
+ completionStatus = readInt(sis);
+ } catch (IOException ioe) {
+ sis.close();
+ throw ioe;
+ }
+
+ // If non-0 it means an error but we need to special-case the
+ // "load" command to ensure that the right exception is thrown.
+ if (completionStatus != 0) {
+ sis.close();
+ if (cmd.equals("load")) {
+ throw new AgentLoadException("Failed to load agent library");
+ } else {
+ throw new IOException("Command failed in target VM");
+ }
+ }
+
+ // Return the input stream so that the command output can be read
+ return sis;
+ }
+
+ // InputStream over a socket
+ private class SocketInputStream extends InputStream {
+ int s;
+
+ public SocketInputStream(int s) {
+ this.s = s;
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = this.read(b, 0, 1);
+ if (n == 1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public synchronized int read(byte[] bs, int off, int len) throws IOException {
+ if ((off < 0) || (off > bs.length) || (len < 0) ||
+ ((off + len) > bs.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0)
+ return 0;
+
+ return SolarisVirtualMachine.read(s, bs, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ SolarisVirtualMachine.close(s);
+ }
+ }
+
+ // The door is attached to .java_pid<pid> in the temporary directory.
+ private int openDoor(int pid) throws IOException {
+ String path = tmpdir + "/.java_pid" + pid;;
+ fd = open(path);
+
+ // Check that the file owner/permission to avoid attaching to
+ // bogus process
+ try {
+ checkPermissions(path);
+ } catch (IOException ioe) {
+ close(fd);
+ throw ioe;
+ }
+ return fd;
+ }
+
+ // On Solaris/Linux a simple handshake is used to start the attach mechanism
+ // if not already started. The client creates a .attach_pid<pid> file in the
+ // target VM's working directory (or temporary directory), and the SIGQUIT
+ // handler checks for the file.
+ private File createAttachFile(int pid) throws IOException {
+ String fn = ".attach_pid" + pid;
+ String path = "/proc/" + pid + "/cwd/" + fn;
+ File f = new File(path);
+ try {
+ f.createNewFile();
+ } catch (IOException x) {
+ f = new File(tmpdir, fn);
+ f.createNewFile();
+ }
+ return f;
+ }
+
+ //-- native methods
+
+ static native int open(String path) throws IOException;
+
+ static native void close(int fd) throws IOException;
+
+ static native int read(int fd, byte buf[], int off, int buflen) throws IOException;
+
+ static native void checkPermissions(String path) throws IOException;
+
+ static native void sigquit(int pid) throws IOException;
+
+ // enqueue a command (and arguments) to the given door
+ static native int enqueue(int fd, String cmd, Object ... args)
+ throws IOException;
+
+ static {
+ System.loadLibrary("attach");
+ }
+}
diff --git a/modules/module-impl/agent/src/main/java/sun/tools/attach/WindowsVirtualMachine.java b/modules/module-impl/agent/src/main/java/sun/tools/attach/WindowsVirtualMachine.java
new file mode 100644
index 0000000..d347a65
--- /dev/null
+++ b/modules/module-impl/agent/src/main/java/sun/tools/attach/WindowsVirtualMachine.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package sun.tools.attach;
+
+import com.sun.tools.attach.VirtualMachine;
+import com.sun.tools.attach.AgentLoadException;
+import com.sun.tools.attach.AttachNotSupportedException;
+import com.sun.tools.attach.spi.AttachProvider;
+import sun.tools.attach.HotSpotVirtualMachine;
+import java.io.IOException;
+import java.io.File;
+import java.io.InputStream;
+import java.util.Properties;
+import java.util.Random;
+
+public class WindowsVirtualMachine extends HotSpotVirtualMachine {
+
+ // the enqueue code stub (copied into each target VM)
+ private static byte[] stub;
+
+ private volatile long hProcess; // handle to the process
+
+ public WindowsVirtualMachine(AttachProvider provider, String id)
+ throws AttachNotSupportedException, IOException
+ {
+ super(provider, id);
+
+ int pid;
+ try {
+ pid = Integer.parseInt(id);
+ } catch (NumberFormatException x) {
+ throw new AttachNotSupportedException("Invalid process identifier");
+ }
+ hProcess = openProcess(pid);
+
+ // The target VM might be a pre-6.0 VM so we enqueue a "null" command
+ // which minimally tests that the enqueue function exists in the target
+ // VM.
+ try {
+ enqueue(hProcess, stub, null, null);
+ } catch (IOException x) {
+ throw new AttachNotSupportedException(x.getMessage());
+ }
+ }
+
+ @Override
+ public void detach() throws IOException {
+ synchronized (this) {
+ if (hProcess != -1) {
+ closeProcess(hProcess);
+ hProcess = -1;
+ }
+ }
+ }
+
+ @Override
+ InputStream execute(String cmd, Object ... args)
+ throws AgentLoadException, IOException
+ {
+ assert args.length <= 3; // includes null
+
+ // create a pipe using a random name
+ int r = (new Random()).nextInt();
+ String pipename = "\\\\.\\pipe\\javatool" + r;
+ long hPipe = createPipe(pipename);
+
+ // check if we are detached - in theory it's possible that detach is invoked
+ // after this check but before we enqueue the command.
+ if (hProcess == -1) {
+ closePipe(hPipe);
+ throw new IOException("Detached from target VM");
+ }
+
+ try {
+ // enqueue the command to the process
+ enqueue(hProcess, stub, cmd, pipename, args);
+
+ // wait for command to complete - process will connect with the
+ // completion status
+ connectPipe(hPipe);
+
+ // create an input stream for the pipe
+ PipedInputStream is = new PipedInputStream(hPipe);
+
+ // read completion status
+ int status = readInt(is);
+ if (status != 0) {
+ // special case the load command so that the right exception is thrown
+ if (cmd.equals("load")) {
+ throw new AgentLoadException("Failed to load agent library");
+ } else {
+ throw new IOException("Command failed in target VM");
+ }
+ }
+
+ // return the input stream
+ return is;
+
+ } catch (IOException ioe) {
+ closePipe(hPipe);
+ throw ioe;
+ }
+ }
+
+ // An InputStream based on a pipe to the target VM
+ private class PipedInputStream extends InputStream {
+
+ private long hPipe;
+
+ public PipedInputStream(long hPipe) {
+ this.hPipe = hPipe;
+ }
+
+ @Override
+ public synchronized int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = this.read(b, 0, 1);
+ if (n == 1) {
+ return b[0] & 0xff;
+ } else {
+ return -1;
+ }
+ }
+
+ @Override
+ public synchronized int read(byte[] bs, int off, int len) throws IOException {
+ if ((off < 0) || (off > bs.length) || (len < 0) ||
+ ((off + len) > bs.length) || ((off + len) < 0)) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0)
+ return 0;
+
+ return WindowsVirtualMachine.readPipe(hPipe, bs, off, len);
+ }
+
+ @Override
+ public void close() throws IOException {
+ if (hPipe != -1) {
+ WindowsVirtualMachine.closePipe(hPipe);
+ hPipe = -1;
+ }
+ }
+ }
+
+
+ //-- native methods
+
+ static native void init();
+
+ static native byte[] generateStub();
+
+ static native long openProcess(int pid) throws IOException;
+
+ static native void closeProcess(long hProcess) throws IOException;
+
+ static native long createPipe(String name) throws IOException;
+
+ static native void closePipe(long hPipe) throws IOException;
+
+ static native void connectPipe(long hPipe) throws IOException;
+
+ static native int readPipe(long hPipe, byte buf[], int off, int buflen) throws IOException;
+
+ static native void enqueue(long hProcess, byte[] stub,
+ String cmd, String pipename, Object ... args) throws IOException;
+
+ static {
+ System.loadLibrary("attach");
+ init(); // native initialization
+ stub = generateStub(); // generate stub to copy into target process
+ }
+}
diff --git a/modules/module-impl/agent/src/main/javadoc/resources/org,powermock/modules/agent/package.html b/modules/module-impl/agent/src/main/javadoc/resources/org,powermock/modules/agent/package.html
new file mode 100644
index 0000000..04fef06
--- /dev/null
+++ b/modules/module-impl/agent/src/main/javadoc/resources/org,powermock/modules/agent/package.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<HTML>
+ <HEAD>
+ <TITLE>PowerMock Java Agent package</TITLE>
+ </HEAD>
+ <BODY>
+ The PowerMock agent classes. The PowerMock agent solution is based on the excellent work of Rogério Liesenfeld, founder of JMockit. JMockit license:
+
+ The JMockit Testing Toolkit
+ Copyright (c) 2006-2011 Rogério Liesenfeld
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ </BODY>
+</HTML>
+
+
diff --git a/modules/module-impl/junit3/pom.xml b/modules/module-impl/junit3/pom.xml
new file mode 100644
index 0000000..9295e44
--- /dev/null
+++ b/modules/module-impl/junit3/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit3</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock support module for JUnit 3.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.2</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/PowerMockSuite.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/PowerMockSuite.java
new file mode 100644
index 0000000..c26f689
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/PowerMockSuite.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import org.powermock.modules.junit3.internal.JUnit3TestSuiteChunker;
+import org.powermock.modules.junit3.internal.impl.JUnit3TestSuiteChunkerImpl;
+
+import java.util.Enumeration;
+
+/**
+ * A custom JUnit 3 Suite that must be used to run PowerMock tests under JUnit3.
+ *
+ */
+public class PowerMockSuite extends TestSuite {
+
+ private JUnit3TestSuiteChunker testChunker;
+
+ public PowerMockSuite(String name, Class<? extends TestCase>... testCases) throws Exception {
+ if (name != null) {
+ setName(name);
+ }
+ testChunker = new JUnit3TestSuiteChunkerImpl(testCases);
+ }
+
+ public PowerMockSuite(Class<? extends TestCase>... testCases) throws Exception {
+ this(null, testCases);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(TestResult result) {
+ testChunker.run(result);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void addTest(Test test) {
+ try {
+ testChunker.addTest(test);
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ } else {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void runTest(Test test, TestResult result) {
+ testChunker.runTest(test, result);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public void addTestSuite(Class testClass) {
+ try {
+ testChunker.addTestSuite(testClass);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Test testAt(int index) {
+ return testChunker.testAt(index);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int testCount() {
+ return testChunker.getTestCount();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Enumeration tests() {
+ return testChunker.tests();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int countTestCases() {
+ return testChunker.countTestCases();
+ }
+}
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/JUnit3TestSuiteChunker.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/JUnit3TestSuiteChunker.java
new file mode 100644
index 0000000..36aeab0
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/JUnit3TestSuiteChunker.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3.internal;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import org.powermock.tests.utils.RunnerTestSuiteChunker;
+
+import java.lang.reflect.Method;
+import java.util.Enumeration;
+
+public interface JUnit3TestSuiteChunker extends RunnerTestSuiteChunker {
+
+ /**
+ * Add a class to the test suite. Methods in this class will be checked
+ * according to {@link #shouldExecuteTestForMethod(Class, Method)} to see if
+ * it should be executed.
+ *
+ * @param clazz
+ * The class that should contain test cases.
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ void addTestClassToSuite(Class<?> clazz) throws Exception;
+
+ void run(TestResult result);
+
+ void addTest(Test test) throws Exception;
+
+ void runTest(Test test, TestResult result);
+
+ void addTestSuite(Class<? extends TestCase> testClass) throws Exception;
+
+ Test testAt(int index);
+
+ int countTestCases();
+
+ Enumeration<?> tests();
+}
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/PowerMockJUnit3RunnerDelegate.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/PowerMockJUnit3RunnerDelegate.java
new file mode 100644
index 0000000..8a29f3e
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/PowerMockJUnit3RunnerDelegate.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3.internal;
+
+import junit.framework.Test;
+import junit.framework.TestResult;
+
+import java.util.Enumeration;
+
+public interface PowerMockJUnit3RunnerDelegate {
+
+ public Class<?> getTestClass();
+
+ public int testCount();
+
+ public int countTestCases();
+
+ public void run(TestResult result);
+
+ public void runTest(Test test, TestResult result);
+
+ public Test testAt(int index);
+
+ public Enumeration<?> tests();
+
+ public void setName(String name);
+
+}
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/JUnit3TestSuiteChunkerImpl.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/JUnit3TestSuiteChunkerImpl.java
new file mode 100644
index 0000000..5fc4e91
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/JUnit3TestSuiteChunkerImpl.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3.internal.impl;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.modules.junit3.internal.JUnit3TestSuiteChunker;
+import org.powermock.modules.junit3.internal.PowerMockJUnit3RunnerDelegate;
+import org.powermock.tests.utils.TestChunk;
+import org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+public class JUnit3TestSuiteChunkerImpl extends AbstractTestSuiteChunkerImpl<PowerMockJUnit3RunnerDelegate> implements
+ JUnit3TestSuiteChunker {
+
+ private String name;
+
+ public JUnit3TestSuiteChunkerImpl(Class<? extends TestCase>... testClasses) throws Exception {
+ super(testClasses);
+ try {
+ for (Class<? extends TestCase> testClass : testClasses) {
+ createTestDelegators(testClass, getTestChunksEntries(testClass));
+ }
+ } catch (Exception e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else {
+ throw new RuntimeException(cause);
+ }
+ }
+ }
+
+ public JUnit3TestSuiteChunkerImpl(String name, Class<? extends TestCase>... testClasses) throws Exception {
+ this(testClasses);
+ this.name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected PowerMockJUnit3RunnerDelegate createDelegatorFromClassloader(ClassLoader classLoader, Class<?> testClass,
+ final List<Method> methodsToTest) throws Exception {
+ final Class<?> testClassLoadedByMockedClassLoader = Class.forName(testClass.getName(), false, classLoader);
+ final Class<?> powerMockTestListenerArrayType = Class.forName(PowerMockTestListener[].class.getName(), false,
+ classLoader);
+ Class<?> delegateClass = Class.forName(PowerMockJUnit3RunnerDelegateImpl.class.getName(), false, classLoader);
+ Constructor<?> con = delegateClass.getConstructor(new Class[] { Class.class, Method[].class,
+ powerMockTestListenerArrayType });
+ final PowerMockJUnit3RunnerDelegate newDelegate = (PowerMockJUnit3RunnerDelegate) con.newInstance(new Object[] {
+ testClassLoadedByMockedClassLoader, methodsToTest.toArray(new Method[0]),
+ getPowerMockTestListenersLoadedByASpecificClassLoader(testClass, classLoader) });
+ newDelegate.setName(name);
+ return newDelegate;
+ }
+
+ @Override
+ protected void chunkClass(Class<?> testClass) throws Exception {
+ if (!TestCase.class.isAssignableFrom(testClass)) {
+ throw new IllegalArgumentException(testClass.getName() + " must be a subtype of "
+ + TestCase.class.getName());
+ }
+ super.chunkClass(testClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTestCount() {
+ if (testCount == NOT_INITIALIZED) {
+ testCount = 0;
+ for (PowerMockJUnit3RunnerDelegate delegate : delegates) {
+ testCount += delegate.testCount();
+ }
+ }
+ return testCount;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean shouldExecuteTestForMethod(Class<?> testClass, Method potentialTestMethod) {
+ return potentialTestMethod.getName().startsWith("test")
+ && Modifier.isPublic(potentialTestMethod.getModifiers())
+ && potentialTestMethod.getReturnType().equals(Void.TYPE);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addTest(Test test) throws Exception {
+ if (test == null) {
+ throw new IllegalArgumentException("test cannot be null");
+ }
+
+ if (test instanceof TestCase) {
+ // testSuiteDelegator.addTest(prepareTestCase((TestCase) test));
+ addTestClassToSuite(test.getClass());
+ } else if (test instanceof TestSuite) {
+ final Enumeration<?> tests = ((TestSuite) test).tests();
+ while (tests.hasMoreElements()) {
+ addTest((Test) tests.nextElement());
+ }
+ } else {
+ throw new IllegalArgumentException("The test type " + test.getClass().getName()
+ + " is not supported. Only " + TestCase.class.getName() + " and " + TestSuite.class.getName()
+ + " are supported.");
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addTestSuite(Class<? extends TestCase> testClass) throws Exception {
+ addTestClassToSuite(testClass);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int countTestCases() {
+ int count = 0;
+ for (PowerMockJUnit3RunnerDelegate delegate : delegates) {
+ count += delegate.countTestCases();
+ }
+ return count;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void run(TestResult result) {
+ final Iterator<TestChunk> iterator = getChunkIterator();
+ for (PowerMockJUnit3RunnerDelegate delegate : delegates) {
+ TestChunk next = iterator.next();
+ final PowerMockJUnit3TestListener listener = new PowerMockJUnit3TestListener(next.getClassLoader());
+ result.addListener(listener);
+ // Initialize mock policies for each test
+ new MockPolicyInitializerImpl(delegate.getTestClass()).initialize(this.getClass().getClassLoader());
+ delegate.run(result);
+ result.removeListener(listener);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void runTest(Test test, TestResult result) {
+ final Iterator<TestChunk> iterator = getChunkIterator();
+ for (PowerMockJUnit3RunnerDelegate delegate : delegates) {
+ TestChunk next = iterator.next();
+ final PowerMockJUnit3TestListener listener = new PowerMockJUnit3TestListener(next.getClassLoader());
+ result.addListener(listener);
+ delegate.runTest(test, result);
+ result.removeListener(listener);
+ }
+ }
+
+ private Iterator<TestChunk> getChunkIterator() {
+ List<TestChunk> entrySet = getTestChunks();
+ Iterator<TestChunk> iterator = entrySet.iterator();
+
+ if (delegates.size() != getChunkSize()) {
+ throw new IllegalStateException("Internal error: There must be an equal number of suites and delegates.");
+ }
+ return iterator;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Test testAt(int index) {
+ return delegates.get(getDelegatorIndex(index)).testAt(getInternalTestIndex(index));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void addTestClassToSuite(Class<?> clazz) throws Exception {
+ chunkClass(clazz);
+ if (!delegatesCreatedForTheseClasses.contains(clazz)) {
+ try {
+ createTestDelegators(clazz, getTestChunksEntries(clazz));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public Enumeration<?> tests() {
+ final List<Object> tests = new LinkedList<Object>();
+ for (PowerMockJUnit3RunnerDelegate delegate : delegates) {
+ final Enumeration<?> delegateTests = delegate.tests();
+ while (delegateTests.hasMoreElements()) {
+ tests.add(delegateTests.nextElement());
+ }
+ }
+
+ Enumeration<?> allTests = new Enumeration<Object>() {
+ private volatile int count = 0;
+
+ public boolean hasMoreElements() {
+ return count != tests.size();
+ }
+
+ public Object nextElement() {
+ return tests.get(count++);
+ }
+ };
+
+ return allTests;
+ }
+}
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3RunnerDelegateImpl.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3RunnerDelegateImpl.java
new file mode 100644
index 0000000..af3d2ea
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3RunnerDelegateImpl.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3.internal.impl;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestResult;
+import junit.framework.TestSuite;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.modules.junit3.internal.PowerMockJUnit3RunnerDelegate;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.Vector;
+
+ at SuppressWarnings("unchecked")
+public class PowerMockJUnit3RunnerDelegateImpl extends TestSuite implements PowerMockJUnit3RunnerDelegate {
+
+ private final Method[] methodsToRun;
+
+ private Class<?> testClass;
+
+ public PowerMockJUnit3RunnerDelegateImpl(final Class<?> theClass, Method[] methodsToRun, String name,
+ PowerMockTestListener[] powerListeners) {
+ this(theClass, methodsToRun, powerListeners);
+ testClass = theClass;
+ setName(name);
+ }
+
+ /**
+ * Constructs a TestSuite from the given class. Adds all the methods
+ * starting with "test" as test cases to the suite. Parts of this method was
+ * cut'n'pasted on the train between Malm� and Stockholm.
+ */
+ public PowerMockJUnit3RunnerDelegateImpl(final Class<?> theClass, Method[] methodsToRun, PowerMockTestListener[] powerMockTestListeners) {
+ testClass = theClass;
+ this.methodsToRun = methodsToRun;
+ setName(theClass.getName());
+
+ try {
+ getTestConstructor(theClass); // Avoid generating multiple error
+ // messages
+ } catch (NoSuchMethodException e) {
+ addTest(warning("Class " + theClass.getName() + " has no public constructor TestCase(String name) or TestCase()"));
+ return;
+ }
+
+ if (!Modifier.isPublic(theClass.getModifiers())) {
+ addTest(warning("Class " + theClass.getName() + " is not public"));
+ return;
+ }
+
+ Class<?> superClass = theClass;
+ Vector<?> names = new Vector<Object>();
+ Method addTestMethod = null;
+ Method[] declaredMethods = TestSuite.class.getDeclaredMethods();
+ for (Method method : declaredMethods) {
+ /*
+ * Since the TestSuite class is loaded by another classloader we
+ * look up the method this way (which is not fail-proof, but good
+ * enough).
+ */
+ if (method.getName().equals("addTestMethod")) {
+ addTestMethod = method;
+ }
+ }
+
+ if (addTestMethod == null) {
+ throw new RuntimeException("Internal error: Failed to get addTestMethod for JUnit3.");
+ }
+
+ addTestMethod.setAccessible(true);
+
+ while (Test.class.isAssignableFrom(superClass)) {
+ for (int i = 0; i < methodsToRun.length; i++) {
+ try {
+ addTestMethod.invoke(this, methodsToRun[i], names, theClass);
+ } catch (Exception e) {
+ throw new RuntimeException("Internal error: Failed to execute addTestMethod for JUnit3.");
+ }
+ }
+ superClass = superClass.getSuperclass();
+ }
+ if (testCount() == 0) {
+ addTest(warning("No tests found in " + theClass.getName()));
+ }
+ }
+
+ @Override
+ public Class<?> getTestClass() {
+ return testClass;
+ }
+
+ @Override
+ public void run(TestResult result) {
+ final ClassLoader classloader = this.getClass().getClassLoader();
+ final Thread currentThread = Thread.currentThread();
+ final ClassLoader originalClassLoader = currentThread.getContextClassLoader();
+ currentThread.setContextClassLoader(classloader);
+ try {
+ super.run(result);
+ } finally {
+ currentThread.setContextClassLoader(originalClassLoader);
+ }
+ }
+
+ /**
+ * Returns a test which will fail and log a warning message.
+ */
+ public static Test warning(final String message) {
+ return new TestCase("warning") {
+ @Override
+ protected void runTest() {
+ fail(message);
+ }
+ };
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("Methods ran by this test runner delegate:\n");
+ for (Method method : methodsToRun) {
+ builder.append(method).append("\n");
+ }
+ return builder.toString();
+ }
+
+}
diff --git a/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3TestListener.java b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3TestListener.java
new file mode 100644
index 0000000..1042b1d
--- /dev/null
+++ b/modules/module-impl/junit3/src/main/java/org/powermock/modules/junit3/internal/impl/PowerMockJUnit3TestListener.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit3.internal.impl;
+
+import junit.framework.AssertionFailedError;
+import junit.framework.Test;
+import junit.framework.TestListener;
+import junit.runner.TestRunListener;
+import org.powermock.core.MockRepository;
+
+import java.lang.reflect.Method;
+
+/**
+ * An implementation of the {@link TestRunListener} interface that performs
+ * cleanup after each test so that no state is maintained in PowerMock between
+ * test runs.
+ *
+ */
+public class PowerMockJUnit3TestListener implements TestListener {
+ private ClassLoader mockClassLoader;
+
+ public PowerMockJUnit3TestListener(ClassLoader mockClassLoader) {
+ this.mockClassLoader = mockClassLoader;
+ }
+
+ /**
+ * Does nothing.
+ */
+ @Override
+ public void addError(Test test, Throwable t) {
+ }
+
+ /**
+ * Does nothing.
+ */
+ @Override
+ public void addFailure(Test test, AssertionFailedError t) {
+ }
+
+ @Override
+ public void endTest(Test test) {
+ try {
+ Class<?> powerMockClass = mockClassLoader.loadClass(MockRepository.class.getName());
+ Method method = powerMockClass.getDeclaredMethod("clear");
+ if (method == null) {
+ throw new IllegalStateException("Method clearState was not found in " + MockRepository.class);
+ }
+ method.setAccessible(true);
+ method.invoke(powerMockClass);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Does nothing.
+ */
+ @Override
+ public void startTest(Test test) {
+ }
+}
diff --git a/modules/module-impl/junit4-common/pom.xml b/modules/module-impl/junit4-common/pom.xml
new file mode 100644
index 0000000..6659575
--- /dev/null
+++ b/modules/module-impl/junit4-common/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock support module for all versions of JUnit 4.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/JUnit4TestSuiteChunker.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/JUnit4TestSuiteChunker.java
new file mode 100644
index 0000000..1ec2bd5
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/JUnit4TestSuiteChunker.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.Sortable;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.tests.utils.RunnerTestSuiteChunker;
+
+public interface JUnit4TestSuiteChunker extends RunnerTestSuiteChunker, Filterable, Sortable {
+
+ Description getDescription();
+
+ void run(RunNotifier notifier);
+
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/PowerMockJUnitRunnerDelegate.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/PowerMockJUnitRunnerDelegate.java
new file mode 100644
index 0000000..1721314
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/PowerMockJUnitRunnerDelegate.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+
+public interface PowerMockJUnitRunnerDelegate {
+
+ void run(final RunNotifier notifier);
+
+ Description getDescription();
+
+ int getTestCount();
+
+ Class<?> getTestClass();
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/AbstractCommonPowerMockRunner.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/AbstractCommonPowerMockRunner.java
new file mode 100644
index 0000000..fbdbcf9
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/AbstractCommonPowerMockRunner.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.*;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.MockRepository;
+import org.powermock.modules.junit4.common.internal.JUnit4TestSuiteChunker;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+
+public abstract class AbstractCommonPowerMockRunner extends Runner implements Filterable, Sortable {
+
+ private JUnit4TestSuiteChunker suiteChunker;
+
+ public AbstractCommonPowerMockRunner(Class<?> klass,
+ Class<? extends PowerMockJUnitRunnerDelegate> runnerDelegateImplClass) throws Exception {
+ suiteChunker = new JUnit4TestSuiteChunkerImpl(klass, runnerDelegateImplClass);
+ /*
+ * For extra safety clear the MockitoRepository on each new
+ * instantiation of the runner. This is good in cases where a previous
+ * test has used e.g. PowerMock#createMock(..) to create a mock without
+ * using this runner. That means that there's some state left in the
+ * MockRepository that hasn't been cleared. Currently clearing the
+ * MockRepository from any classloader will clear the previous state but
+ * it's not certain that this is always the case.
+ */
+ MockRepository.clear();
+ }
+
+ @Override
+ public Description getDescription() {
+ return suiteChunker.getDescription();
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ try {
+ suiteChunker.run(notifier);
+ } finally {
+ // To avoid out of memory errors!
+ suiteChunker = null;
+ }
+ }
+
+ @Override
+ public synchronized int testCount() {
+ return suiteChunker.getTestCount();
+ }
+
+ @Override
+ public void filter(Filter filter) throws NoTestsRemainException {
+ suiteChunker.filter(filter);
+ }
+
+ @Override
+ public void sort(Sorter sorter) {
+ suiteChunker.sort(sorter);
+ }
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestMethodChecker.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestMethodChecker.java
new file mode 100644
index 0000000..c5238cb
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestMethodChecker.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.junit4.common.internal.impl;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ *
+ */
+public class JUnit4TestMethodChecker {
+ private final Class<?> testClass;
+ private final Method potentialTestMethod;
+
+ public JUnit4TestMethodChecker(Class<?> testClass, Method potentialTestMethod) {
+ this.testClass = testClass;
+ this.potentialTestMethod = potentialTestMethod;
+ }
+
+ public boolean isTestMethod() {
+ return isJUnit3TestMethod() || isJUnit4TestMethod();
+ }
+
+ protected boolean isJUnit4TestMethod() {return potentialTestMethod.isAnnotationPresent(Test.class);}
+
+ protected boolean isJUnit3TestMethod() {
+ return potentialTestMethod.getName().startsWith("test")
+ && Modifier.isPublic(potentialTestMethod.getModifiers())
+ && potentialTestMethod.getReturnType()
+ .equals(Void.TYPE) && TestCase.class.isAssignableFrom(testClass);
+ }
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestSuiteChunkerImpl.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestSuiteChunkerImpl.java
new file mode 100644
index 0000000..d3bf9b2
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnit4TestSuiteChunkerImpl.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+import org.junit.Test;
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.manipulation.Sortable;
+import org.junit.runner.manipulation.Sorter;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.reporter.MockingFrameworkReporter;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.core.spi.testresult.TestSuiteResult;
+import org.powermock.core.spi.testresult.impl.TestSuiteResultImpl;
+import org.powermock.modules.junit4.common.internal.JUnit4TestSuiteChunker;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+import org.powermock.tests.utils.TestChunk;
+import org.powermock.tests.utils.impl.AbstractTestSuiteChunkerImpl;
+import org.powermock.tests.utils.impl.PowerMockTestNotifierImpl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+public class JUnit4TestSuiteChunkerImpl extends AbstractTestSuiteChunkerImpl<PowerMockJUnitRunnerDelegate> implements
+ JUnit4TestSuiteChunker, Filterable, Sortable {
+
+ private static final Class<? extends Annotation> testMethodAnnotation = Test.class;
+
+ private Description description;
+ private final Class<? extends PowerMockJUnitRunnerDelegate> runnerDelegateImplementationType;
+
+
+ public JUnit4TestSuiteChunkerImpl(Class<?> testClass,
+ Class<? extends PowerMockJUnitRunnerDelegate> runnerDelegateImplementationType) throws Exception {
+ super(testClass);
+ if (testClass == null) {
+ throw new IllegalArgumentException("You must supply a test class");
+ }
+
+ if (runnerDelegateImplementationType == null) {
+ throw new IllegalArgumentException("Runner delegate type cannot be null.");
+ }
+
+ this.runnerDelegateImplementationType = runnerDelegateImplementationType;
+
+ try {
+ createTestDelegators(testClass, getTestChunksEntries(testClass));
+ } catch (InvocationTargetException e) {
+ final Throwable cause = e.getCause();
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new RuntimeException(cause);
+ }
+ }
+
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ List<TestChunk> chunkEntries = getTestChunks();
+ Iterator<TestChunk> iterator = chunkEntries.iterator();
+
+ if (delegates.size() != getChunkSize()) {
+ throw new IllegalStateException("Internal error: There must be an equal number of suites and delegates.");
+ }
+
+ final Class<?> testClass = getTestClasses()[0];
+ final PowerMockTestListener[] powerMockTestListeners = (PowerMockTestListener[]) getPowerMockTestListenersLoadedByASpecificClassLoader(
+ testClass, this.getClass().getClassLoader());
+
+ final Set<Method> allMethods = new LinkedHashSet<Method>();
+ for (TestChunk testChunk : getTestChunks()) {
+ allMethods.addAll(testChunk.getTestMethodsToBeExecutedByThisClassloader());
+ }
+
+ final Method[] allMethodsAsArray = allMethods.toArray(new Method[allMethods.size()]);
+ final PowerMockTestNotifier powerMockTestNotifier = new PowerMockTestNotifierImpl(powerMockTestListeners);
+ powerMockTestNotifier.notifyBeforeTestSuiteStarted(testClass, allMethodsAsArray);
+
+ int failureCount = 0;
+ int successCount = 0;
+ int ignoreCount = 0;
+
+ for (PowerMockJUnitRunnerDelegate delegate : delegates) {
+ TestChunk next = iterator.next();
+ final ClassLoader key = next.getClassLoader();
+ PowerMockJUnit4RunListener powerMockListener = new PowerMockJUnit4RunListener(key, powerMockTestNotifier);
+ notifier.addListener(powerMockListener);
+ final ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(key);
+ try {
+ MockingFrameworkReporter mockingFrameworkReporter = getMockingFrameworkReporter();
+ mockingFrameworkReporter.enable();
+ delegate.run(notifier);
+ mockingFrameworkReporter.disable();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoader);
+ }
+ final int failureCountForThisPowerMockListener = powerMockListener.getFailureCount();
+ final int ignoreCountForThisPowerMockListener = powerMockListener.getIgnoreCount();
+ failureCount += failureCountForThisPowerMockListener;
+ ignoreCount += ignoreCountForThisPowerMockListener;
+ successCount += delegate.getTestCount() - failureCountForThisPowerMockListener
+ - ignoreCountForThisPowerMockListener;
+ notifier.removeListener(powerMockListener);
+ }
+
+ final TestSuiteResult testSuiteResult = new TestSuiteResultImpl(failureCount, successCount, getTestCount(),
+ ignoreCount);
+ powerMockTestNotifier.notifyAfterTestSuiteEnded(testClass, allMethodsAsArray, testSuiteResult);
+ }
+
+ private MockingFrameworkReporter getMockingFrameworkReporter() {return getFrameworkReporterFactory().create();}
+
+ @Override
+ public boolean shouldExecuteTestForMethod(Class<?> testClass, Method potentialTestMethod) {
+ return new JUnit4TestMethodChecker(testClass, potentialTestMethod).isTestMethod();
+ }
+
+ @Override
+ protected Class<? extends Annotation> testMethodAnnotation() {
+ return testMethodAnnotation;
+ }
+
+ @Override
+ protected PowerMockJUnitRunnerDelegate createDelegatorFromClassloader(ClassLoader classLoader, Class<?> testClass,
+ final List<Method> methodsToTest) throws Exception {
+
+ Set<String> methodNames = new HashSet<String>();
+ for (Method method : methodsToTest) {
+ methodNames.add(method.getName());
+ }
+
+ final Class<?> testClassLoadedByMockedClassLoader = Class.forName(testClass.getName(), false, classLoader);
+
+ /*
+ * Array classes cannot be loaded be classloader.loadClass(..) in JDK 6.
+ * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6500212.
+ */
+ final Class<?> powerMockTestListenerArrayType = Class.forName(PowerMockTestListener[].class.getName(), false,
+ classLoader);
+ final Class<?> delegateClass = Class.forName(runnerDelegateImplementationType.getName(), false, classLoader);
+ Constructor<?> con = delegateClass.getConstructor(new Class[] { Class.class, String[].class,
+ powerMockTestListenerArrayType });
+ return (PowerMockJUnitRunnerDelegate) con.newInstance(new Object[] {
+ testClassLoadedByMockedClassLoader, methodNames.toArray(new String[methodNames.size()]),
+ getPowerMockTestListenersLoadedByASpecificClassLoader(testClass, classLoader) });
+ }
+
+ @Override
+ public synchronized int getTestCount() {
+ if (testCount == NOT_INITIALIZED) {
+ testCount = 0;
+ for (PowerMockJUnitRunnerDelegate delegate : delegates) {
+ testCount += delegate.getTestCount();
+ }
+ }
+ return testCount;
+ }
+
+ @Override
+ public Description getDescription() {
+ if (description == null) {
+ if (delegates.size() == 0) {
+ /*
+ * This happens if Test A extends Test B and B uses the @RunWith
+ * annotation and there are no tests defined in class B.
+ */
+ return Description.createTestDescription(this.getClass(), "no tests in this class");
+ }
+
+ // Use the first delegator as the base for the description.
+ PowerMockJUnitRunnerDelegate delegate = delegates.get(0);
+ description = delegate.getDescription();
+
+ /*
+ * Add the remaining descriptions of all the chunked delegators. We
+ * do this to make sure that we avoid adding chunks as "Unrooted
+ * tests".
+ */
+ for (int i = 1; i < delegates.size(); i++) {
+ // Get the method-level descriptions
+ ArrayList<Description> children = delegates.get(i).getDescription().getChildren();
+ // Add all method-level descriptions to the main description.
+ for (Description methodDescription : children) {
+ description.addChild(methodDescription);
+ }
+ }
+ }
+ return description;
+ }
+
+ @Override
+ public void filter(Filter filter) throws NoTestsRemainException {
+ for (Object delegate : delegates) {
+ if (delegate instanceof Filterable) {
+ ((Filterable) delegate).filter(filter);
+ }
+ }
+ }
+
+ @Override
+ public void sort(Sorter sorter) {
+ for (Object delegate : delegates) {
+ if (delegate instanceof Sortable) {
+ ((Sortable) delegate).sort(sorter);
+ }
+ }
+ }
+
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersion.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersion.java
new file mode 100644
index 0000000..4526fc2
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersion.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+import junit.runner.Version;
+
+public class JUnitVersion {
+
+ public static boolean isGreaterThanOrEqualTo(String version) {
+ final String currentVersion = getJUnitVersion();
+ return new VersionComparator().compare(currentVersion, version) >= 0;
+ }
+
+ public static String getJUnitVersion() {
+ return Version.id();
+ }
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/PowerMockJUnit4RunListener.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/PowerMockJUnit4RunListener.java
new file mode 100644
index 0000000..98123b7
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/PowerMockJUnit4RunListener.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+
+public class PowerMockJUnit4RunListener extends RunListener {
+
+ private final ClassLoader mockClassLoader;
+
+ private int failureCount;
+
+ private int ignoreCount;
+
+ private boolean currentTestSuccessful = true;
+
+ private final PowerMockTestNotifier powerMockTestNotifier;
+
+ public PowerMockJUnit4RunListener(ClassLoader mockClassLoader, PowerMockTestNotifier powerMockTestNotifier) {
+ this.mockClassLoader = mockClassLoader;
+ this.powerMockTestNotifier = powerMockTestNotifier;
+ }
+
+ /**
+ * Performs clean up after each test. The {@link MockRepository#clear()}
+ * methods has to be called by the correct class loader for the state to be
+ * cleared. Therefore it is invoked using reflection when the class is
+ * loaded from the correct class loader.
+ */
+ @Override
+ public void testFinished(Description description1) throws Exception {
+ Class<?> mockRepositoryClass = mockClassLoader.loadClass(MockRepository.class.getName());
+ try {
+ notifyListenersOfTestResult();
+ } finally {
+ // Clear state
+ Whitebox.invokeMethod(mockRepositoryClass, "clear");
+ }
+ }
+
+ /**
+ * @return The number of failed tests.
+ */
+ public int getFailureCount() {
+ return failureCount;
+ }
+
+ /**
+ * @return The number of successful tests.
+ */
+ public int getIgnoreCount() {
+ return ignoreCount;
+ }
+
+ @Override
+ public void testFailure(Failure failure) throws Exception {
+ currentTestSuccessful = false;
+ failureCount++;
+ }
+
+ @Override
+ public void testIgnored(Description description) throws Exception {
+ ignoreCount++;
+ }
+
+ private void notifyListenersOfTestResult() {
+ try {
+ powerMockTestNotifier.notifyAfterTestMethod(currentTestSuccessful);
+ } finally {
+ currentTestSuccessful = true;
+ }
+ }
+}
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionComparator.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionComparator.java
new file mode 100644
index 0000000..cca08b6
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionComparator.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+import java.util.Comparator;
+
+/**
+ * This code is copied from http://stackoverflow.com/questions/198431/how-do-you-compare-two-version-strings-in-java
+ */
+class VersionComparator implements Comparator {
+
+ public boolean equals(Object o1, Object o2) {
+ return compare(o1, o2) == 0;
+ }
+
+ @Override
+ public int compare(Object o1, Object o2) {
+ String version1 = (String) o1;
+ String version2 = (String) o2;
+
+ VersionTokenizer tokenizer1 = new VersionTokenizer(version1);
+ VersionTokenizer tokenizer2 = new VersionTokenizer(version2);
+
+ int number1 = 0, number2 = 0;
+ String suffix1 = "", suffix2 = "";
+
+ while (tokenizer1.MoveNext()) {
+ if (!tokenizer2.MoveNext()) {
+ do {
+ number1 = tokenizer1.getNumber();
+ suffix1 = tokenizer1.getSuffix();
+ if (number1 != 0 || suffix1.length() != 0) {
+ // Version one is longer than number two, and non-zero
+ return 1;
+ }
+ }
+ while (tokenizer1.MoveNext());
+
+ // Version one is longer than version two, but zero
+ return 0;
+ }
+
+ number1 = tokenizer1.getNumber();
+ suffix1 = tokenizer1.getSuffix();
+ number2 = tokenizer2.getNumber();
+ suffix2 = tokenizer2.getSuffix();
+
+ if (number1 < number2) {
+ // Number one is less than number two
+ return -1;
+ }
+ if (number1 > number2) {
+ // Number one is greater than number two
+ return 1;
+ }
+
+ boolean empty1 = suffix1.length() == 0;
+ boolean empty2 = suffix2.length() == 0;
+
+ if (empty1 && empty2) continue; // No suffixes
+ if (empty1) return 1; // First suffix is empty (1.2 > 1.2b)
+ if (empty2) return -1; // Second suffix is empty (1.2a < 1.2)
+
+ // Lexical comparison of suffixes
+ int result = suffix1.compareTo(suffix2);
+ if (result != 0) return result;
+
+ }
+ if (tokenizer2.MoveNext()) {
+ do {
+ number2 = tokenizer2.getNumber();
+ suffix2 = tokenizer2.getSuffix();
+ if (number2 != 0 || suffix2.length() != 0) {
+ // Version one is longer than version two, and non-zero
+ return -1;
+ }
+ }
+ while (tokenizer2.MoveNext());
+
+ // Version two is longer than version one, but zero
+ return 0;
+ }
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionTokenizer.java b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionTokenizer.java
new file mode 100644
index 0000000..5e3d1dc
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/main/java/org/powermock/modules/junit4/common/internal/impl/VersionTokenizer.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.common.internal.impl;
+
+/**
+ * This code is copied from http://stackoverflow.com/questions/198431/how-do-you-compare-two-version-strings-in-java
+ */
+class VersionTokenizer {
+ private final String _versionString;
+ private final int _length;
+
+ private int _position;
+ private int _number;
+ private String _suffix;
+
+ public int getNumber() {
+ return _number;
+ }
+
+ public String getSuffix() {
+ return _suffix;
+ }
+
+ public VersionTokenizer(String versionString) {
+ if (versionString == null)
+ throw new IllegalArgumentException("versionString is null");
+
+ _versionString = versionString;
+ _length = versionString.length();
+ }
+
+ public boolean MoveNext() {
+ _number = 0;
+ _suffix = "";
+
+ // No more characters
+ if (_position >= _length)
+ return false;
+
+ while (_position < _length) {
+ char c = _versionString.charAt(_position);
+ if (c < '0' || c > '9') break;
+ _number = _number * 10 + (c - '0');
+ _position++;
+ }
+
+ int suffixStart = _position;
+
+ while (_position < _length) {
+ char c = _versionString.charAt(_position);
+ if (c == '.') break;
+ _position++;
+ }
+
+ _suffix = _versionString.substring(suffixStart, _position);
+
+ if (_position < _length) _position++;
+
+ return true;
+ }
+}
diff --git a/modules/module-impl/junit4-common/src/test/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersionTest.java b/modules/module-impl/junit4-common/src/test/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersionTest.java
new file mode 100644
index 0000000..1bb3ee7
--- /dev/null
+++ b/modules/module-impl/junit4-common/src/test/java/org/powermock/modules/junit4/common/internal/impl/JUnitVersionTest.java
@@ -0,0 +1,39 @@
+package org.powermock.modules.junit4.common.internal.impl;
+
+import org.junit.Test;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public class JUnitVersionTest {
+
+ @Test public void
+ parses_version_numbers_with_chars() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.90b2"), is(false));
+ }
+
+ @Test public void
+ parses_version_numbers_with_dash_snapshot() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.19-SNAPSHOT"), is(false));
+ }
+
+ @Test public void
+ parses_version_numbers_with_dash_snapshot_where_version_is_before_current() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.1-SNAPSHOT"), is(true));
+ }
+
+ @Test public void
+ parses_version_numbers_major_and_minor_versions() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.1.5"), is(true));
+ }
+
+ @Test public void
+ parses_version_numbers_major_and_several_minor_versions() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.44.5.6"), is(false));
+ }
+
+ @Test public void
+ parses_4_11_beta_1() {
+ assertThat(JUnitVersion.isGreaterThanOrEqualTo("4.111-beta-1"), is(false));
+ }
+}
diff --git a/modules/module-impl/junit4-legacy/pom.xml b/modules/module-impl/junit4-legacy/pom.xml
new file mode 100644
index 0000000..bc2d7df
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock support module for JUnit 4.0-4.3.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.3</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock.tests</groupId>
+ <artifactId>powermock-tests-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/PowerMockRunner.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/PowerMockRunner.java
new file mode 100644
index 0000000..6fc5586
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/PowerMockRunner.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.legacy;
+
+import org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner;
+import org.powermock.modules.junit4.legacy.internal.impl.PowerMockJUnit4LegacyRunnerDelegateImpl;
+
+public class PowerMockRunner extends AbstractCommonPowerMockRunner {
+
+ public PowerMockRunner(Class<?> klass) throws Exception {
+ super(klass, PowerMockJUnit4LegacyRunnerDelegateImpl.class);
+ }
+}
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyFilter.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyFilter.java
new file mode 100644
index 0000000..13ca35c
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyFilter.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.legacy.internal.impl;
+
+import org.junit.runner.Description;
+import org.junit.runner.manipulation.Filter;
+
+/**
+ * A JUnit filter that will filter the methods specified in String[] passed to
+ * the constructor (i.e. these are the only tests that will be run for a
+ * particular test class).
+ *
+ * @author Johan Haleby
+ */
+public class PowerMockJUnit4LegacyFilter extends Filter {
+
+ private final String[] methodNamesToRun;
+
+ public PowerMockJUnit4LegacyFilter(String[] methodNamesToRun) {
+ this.methodNamesToRun = methodNamesToRun;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String describe() {
+ return methodNamesToRun.length + " tests.";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean shouldRun(Description description) {
+ boolean shouldRun = false;
+ for (String testMethodName : methodNamesToRun) {
+ if (testMethodName.equals(extractMethodName(description))) {
+ shouldRun = true;
+ break;
+ }
+ }
+ return shouldRun;
+ }
+
+ private String extractMethodName(Description description) {
+ final String displayName = description.getDisplayName();
+ /*
+ * The test method name is the string to the left of the first
+ * parenthesis.
+ * testSayPrivateStatic(org.powermock.modules.junit4.legacy.singleton.StupidSingletonTest)
+ * is an example of a display name.
+ */
+ final int indexOfParenthesis = displayName.indexOf('(');
+ if (indexOfParenthesis == -1) {
+ throw new RuntimeException(
+ "Internal error: Failed to find the test method name.");
+ }
+ return displayName.substring(0, indexOfParenthesis);
+ }
+}
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyRunnerDelegateImpl.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyRunnerDelegateImpl.java
new file mode 100644
index 0000000..d8eb930
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/PowerMockJUnit4LegacyRunnerDelegateImpl.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.legacy.internal.impl;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.internal.runners.BeforeAndAfterRunner;
+import org.junit.internal.runners.InitializationError;
+import org.junit.internal.runners.TestClassRunner;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+import org.powermock.modules.junit4.legacy.internal.impl.testcaseworkaround.PowerMockJUnit4LegacyTestClassMethodsRunner;
+import org.powermock.modules.junit4.legacy.internal.impl.testcaseworkaround.PowerMockJUnit4LegacyTestIntrospector;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+
+/**
+ * A JUnit4 legacy (i.e. v4.0-4.3) test runner that only runs a specified set of
+ * test methods in a test class.
+ *
+ * <p>
+ * Most parts of this class is essentially a rip off from
+ * {@link TestClassRunner} used in JUnit 4.3.
+ *
+ * @see TestClassRunner
+ *
+ */
+public class PowerMockJUnit4LegacyRunnerDelegateImpl extends TestClassRunner implements PowerMockJUnitRunnerDelegate {
+
+ private final int testCount;
+
+ public PowerMockJUnit4LegacyRunnerDelegateImpl(Class<?> klass, String[] methodsToRun,
+ PowerMockTestListener[] listeners) throws InitializationError, NoTestsRemainException {
+ super(klass, new PowerMockJUnit4LegacyTestClassMethodsRunner(klass,
+ listeners == null ? new PowerMockTestListener[0] : listeners));
+ filter(new PowerMockJUnit4LegacyFilter(methodsToRun));
+
+ testCount = methodsToRun.length;
+ }
+
+ public PowerMockJUnit4LegacyRunnerDelegateImpl(Class<?> klass, String[] methodsToRun) throws InitializationError,
+ NoTestsRemainException {
+ this(klass, methodsToRun, null);
+ }
+
+ @Override
+ public void run(final RunNotifier notifier) {
+ BeforeAndAfterRunner runner = new BeforeAndAfterRunner(getTestClass(), BeforeClass.class, AfterClass.class,
+ null) {
+
+ @Override
+ protected void runUnprotected() {
+ fEnclosedRunner.run(notifier);
+ }
+
+ @Override
+ protected void addFailure(Throwable targetException) {
+ notifier.fireTestFailure(new Failure(getDescription(), targetException));
+ }
+ };
+
+ Whitebox.setInternalState(runner, "fTestIntrospector",
+ new PowerMockJUnit4LegacyTestIntrospector(getTestClass()), BeforeAndAfterRunner.class);
+
+ // Initialize mock policies for each test
+ final ClassLoader classLoader = this.getClass().getClassLoader();
+ new MockPolicyInitializerImpl(getTestClass()).initialize(classLoader);
+ Thread.currentThread().setContextClassLoader(classLoader);
+ runner.runProtected();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int getTestCount() {
+ return testCount;
+ }
+
+ @Override
+ public Class<?> getTestClass() {
+ return super.getTestClass();
+ }
+}
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestClassMethodsRunner.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestClassMethodsRunner.java
new file mode 100644
index 0000000..ccfa15a
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestClassMethodsRunner.java
@@ -0,0 +1,100 @@
+package org.powermock.modules.junit4.legacy.internal.impl.testcaseworkaround;
+
+import junit.framework.TestCase;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.internal.runners.TestClassMethodsRunner;
+import org.junit.internal.runners.TestMethodRunner;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+import org.powermock.tests.utils.impl.PowerMockTestNotifierImpl;
+import org.powermock.tests.utils.impl.StaticConstructorSuppressExtractorImpl;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Since {@link TestClassMethodsRunner} creates a new instance of
+ * TestInterceptor in its constructor we need to manually lookup the additional
+ * methods that should be added when extending from <code>TestCase</code>.
+ */
+public class PowerMockJUnit4LegacyTestClassMethodsRunner extends TestClassMethodsRunner {
+
+ private final PowerMockTestNotifier powerMockTestNotifier;
+
+ @SuppressWarnings("unchecked")
+ public PowerMockJUnit4LegacyTestClassMethodsRunner(Class<?> klass, PowerMockTestListener[] powerMockTestListeners) {
+ super(klass);
+ this.powerMockTestNotifier = new PowerMockTestNotifierImpl(powerMockTestListeners);
+ List<Method> testMethods = (List<Method>) Whitebox.getInternalState(this, "fTestMethods", TestClassMethodsRunner.class);
+ testMethods.addAll(getAdditionalTestMethods(klass));
+ }
+
+ private List<Method> getAdditionalTestMethods(Class<?> klass) {
+ List<Method> additionalMethods = new LinkedList<Method>();
+ if (klass != null && klass.getSuperclass().equals(TestCase.class)) {
+ /*
+ * We now know that we need to add additional test methods because
+ * JUnit4 ignores public methods with no @Test annotation when
+ * extending from TestCase.
+ */
+ Method[] methods = klass.getMethods();
+ for (Method method : methods) {
+ if (isAdditionalTestMethod(method)) {
+ additionalMethods.add(method);
+ }
+ }
+ }
+ return additionalMethods;
+
+ }
+
+ private boolean isAdditionalTestMethod(Method method) {
+ if (!method.isAnnotationPresent(Ignore.class) && method.getName().startsWith("test") && Modifier.isPublic(method.getModifiers())
+ && method.getReturnType().equals(Void.TYPE) && method.getAnnotation(Test.class) == null) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ protected TestMethodRunner createMethodRunner(Object test, Method method, RunNotifier notifier) {
+ return new PowerMockJUnit4LegacyTestMethodRunner(test, method, notifier, methodDescription(method), powerMockTestNotifier);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void run(RunNotifier notifier) {
+ final List<Method> methods = (List<Method>) Whitebox.getInternalState(this, "fTestMethods");
+ if (methods.isEmpty())
+ notifier.testAborted(getDescription(), new Exception("No runnable methods"));
+ for (Method method : methods) {
+ final StaticConstructorSuppressExtractorImpl staticConstructorSuppressExtractorImpl = new StaticConstructorSuppressExtractorImpl();
+ Class<?> testType = getTestClass();
+ final ClassLoader thisClassLoader = getClass().getClassLoader();
+ if (!thisClassLoader.equals(testType.getClassLoader())) {
+ /*
+ * The test is loaded from another classloader, this means that
+ * we cannot get the correct annotations if we don't load the
+ * class from the correct class loader
+ */
+ try {
+ testType = thisClassLoader.loadClass(testType.getName());
+ } catch (ClassNotFoundException e) {
+ // This should never happen
+ throw new RuntimeException("Internal error in PowerMock", e);
+ }
+ }
+ if (staticConstructorSuppressExtractorImpl.getTestClasses(method) == null) {
+ staticConstructorSuppressExtractorImpl.getTestClasses(testType);
+ }
+
+ invokeTestMethod(method, notifier);
+ }
+ }
+
+}
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestIntrospector.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestIntrospector.java
new file mode 100644
index 0000000..0e25744
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestIntrospector.java
@@ -0,0 +1,38 @@
+package org.powermock.modules.junit4.legacy.internal.impl.testcaseworkaround;
+
+import org.junit.Test;
+import org.junit.Test.None;
+import org.junit.internal.runners.TestIntrospector;
+
+import java.lang.reflect.Method;
+
+/**
+ * A custom {@link TestIntrospector} that supports methods not annotated by the
+ * Test annotation but should still be executed in the test case. This is
+ * actually a workaround for the JUnit 4 test runner when the test case extends
+ * from the <code>TestCase</code> class.
+ */
+public class PowerMockJUnit4LegacyTestIntrospector extends TestIntrospector {
+
+ private static final long NO_TIMEOUT = 0L;
+
+ public PowerMockJUnit4LegacyTestIntrospector(Class<?> testClass) {
+ super(testClass);
+ }
+
+ @SuppressWarnings("all")
+ public long getTimeout(Method method) {
+ Test annotation = method.getAnnotation(Test.class);
+ long timeout = annotation == null ? NO_TIMEOUT : annotation.timeout();
+ return timeout;
+ }
+
+ @SuppressWarnings("all")
+ public Class<? extends Throwable> expectedException(Method method) {
+ Test annotation = method.getAnnotation(Test.class);
+ if (annotation == null || annotation.expected() == None.class)
+ return null;
+ else
+ return annotation.expected();
+ }
+}
diff --git a/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestMethodRunner.java b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestMethodRunner.java
new file mode 100644
index 0000000..55b4acf
--- /dev/null
+++ b/modules/module-impl/junit4-legacy/src/main/java/org/powermock/modules/junit4/legacy/internal/impl/testcaseworkaround/PowerMockJUnit4LegacyTestMethodRunner.java
@@ -0,0 +1,132 @@
+package org.powermock.modules.junit4.legacy.internal.impl.testcaseworkaround;
+
+import junit.framework.TestCase;
+import org.junit.internal.runners.BeforeAndAfterRunner;
+import org.junit.internal.runners.TestIntrospector;
+import org.junit.internal.runners.TestMethodRunner;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * This class is needed because the test method runner creates a new instance of
+ * a {@link TestIntrospector} in its constructor. The TestIntrospector needs to
+ * be changed in order to support methods not annotated with Test to avoid
+ * NPE's.
+ * <p>
+ * This class also executes the setUp and tearDown methods if the test case
+ * extends TestCase. Another thing it does is to invoke all PowerMock test
+ * listeners for events.
+ */
+public class PowerMockJUnit4LegacyTestMethodRunner extends TestMethodRunner {
+
+ private final PowerMockJUnit4LegacyTestIntrospector testIntrospector;
+
+ private final Method method;
+ private final Description description;
+ private final RunNotifier notifier;
+
+ private final PowerMockTestNotifier powerMockTestNotifier;
+
+ public PowerMockJUnit4LegacyTestMethodRunner(Object test, Method method, RunNotifier notifier,
+ Description description, PowerMockTestNotifier powerMockTestNotifier) {
+ super(test, method, notifier, description);
+ this.method = method;
+ this.description = description;
+ this.notifier = notifier;
+ this.powerMockTestNotifier = powerMockTestNotifier;
+ testIntrospector = new PowerMockJUnit4LegacyTestIntrospector(test.getClass());
+ Whitebox.setInternalState(this, "fTestIntrospector", testIntrospector, TestMethodRunner.class);
+ Whitebox.setInternalState(this, "fTestIntrospector", testIntrospector, BeforeAndAfterRunner.class);
+ }
+
+ @Override
+ public void run() {
+ if (testIntrospector.isIgnored(method)) {
+ notifier.fireTestIgnored(description);
+ return;
+ }
+ notifier.fireTestStarted(description);
+ try {
+ powerMockTestNotifier.notifyBeforeTestMethod(Whitebox.getInternalState(this, "fTest"), method,
+ new Object[0]);
+ long timeout = testIntrospector.getTimeout(method);
+
+ // Execute the the setUp method if needed
+ executeMethodInTestInstance("setUp");
+ if (timeout > 0) {
+ // The runWithTimeout method is private in the super class,
+ // invoke it using reflection.
+ Whitebox.invokeMethod(this, TestMethodRunner.class, "runWithTimeout", timeout);
+ } else {
+ Whitebox.invokeMethod(this, TestMethodRunner.class, "runMethod");
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ } finally {
+ try {
+ executeMethodInTestInstance("tearDown");
+ } finally {
+ notifier.fireTestFinished(description);
+ }
+ }
+ }
+
+ /**
+ * This method takes care of executing a method in the test object <i>if</i>
+ * this object extends from {@link TestCase}. It can be used to execute the
+ * setUp and tearDown methods for example.
+ */
+ private void executeMethodInTestInstance(String methodName) {
+ if (TestCase.class.isAssignableFrom(Whitebox.getInternalState(this, "fTest").getClass())) {
+ Object object = Whitebox.getInternalState(this, "fTest");
+ try {
+ if (object != null) {
+ Whitebox.invokeMethod(object, methodName);
+ }
+ } catch (Throwable e) {
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @Override
+ protected void runUnprotected() {
+ try {
+ executeMethodBody();
+ if (expectsException())
+ addFailure(new AssertionError("Expected exception: " + expectedException().getName()));
+ } catch (InvocationTargetException e) {
+ Throwable actual = e.getTargetException();
+ if (!expectsException())
+ addFailure(actual);
+ else if (isUnexpected(actual)) {
+ String message = "Unexpected exception, expected<" + expectedException().getName() + "> but was<"
+ + actual.getClass().getName() + ">";
+ addFailure(new Exception(message, actual));
+ }
+ } catch (Throwable e) {
+ addFailure(e);
+ }
+ }
+
+ private boolean isUnexpected(Throwable exception) {
+ return !expectedException().isAssignableFrom(exception.getClass());
+ }
+
+ private boolean expectsException() {
+ return expectedException() != null;
+ }
+
+ private Class<? extends Throwable> expectedException() {
+ return testIntrospector.expectedException(method);
+ }
+
+}
diff --git a/modules/module-impl/junit4-rule-agent/pom.xml b/modules/module-impl/junit4-rule-agent/pom.xml
new file mode 100644
index 0000000..eb4a688
--- /dev/null
+++ b/modules/module-impl/junit4-rule-agent/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock support module for JUnit 4.x rules with Java agent
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit4-rule-agent/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java b/modules/module-impl/junit4-rule-agent/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java
new file mode 100644
index 0000000..d9326c9
--- /dev/null
+++ b/modules/module-impl/junit4-rule-agent/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.rule;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.core.MockRepository;
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.core.agent.JavaAgentFrameworkRegister;
+import org.powermock.core.agent.JavaAgentFrameworkRegisterFactory;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.agent.support.JavaAgentClassRegisterImpl;
+import org.powermock.modules.agent.support.PowerMockAgentTestInitializer;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.proxyframework.ClassLoaderRegisterProxyFramework;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+public class PowerMockRule implements MethodRule {
+ static {
+ if (PowerMockRule.class.getClassLoader() != ClassLoader.getSystemClassLoader()) {
+ throw new IllegalStateException("PowerMockRule can only be used with the system classloader but was loaded by " + PowerMockRule.class.getClassLoader());
+ }
+ PowerMockAgent.initializeIfPossible();
+ }
+
+ @Override
+ public Statement apply(Statement base, FrameworkMethod method, Object target) {
+
+ JavaAgentClassRegister agentClassRegister = new JavaAgentClassRegisterImpl();
+ PowerMockAgentTestInitializer.initialize(target.getClass(), agentClassRegister);
+
+ return new PowerMockStatement(base, target, agentClassRegister);
+ }
+}
+
+class PowerMockStatement extends Statement {
+ private static final String ANNOTATION_ENABLER = "org.powermock.api.extension.listener.AnnotationEnabler";
+ private final Statement fNext;
+ private final Object target;
+ private final JavaAgentClassRegister agentClassRegister;
+ private final JavaAgentFrameworkRegister javaAgentFrameworkRegister;
+
+ public PowerMockStatement(Statement base, Object target, JavaAgentClassRegister agentClassRegister) {
+ this.fNext = base;
+ this.target = target;
+ this.agentClassRegister = agentClassRegister;
+ this.javaAgentFrameworkRegister = JavaAgentFrameworkRegisterFactory.create();
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ Object annotationEnabler = loadAnnotationEnableIfPresent();
+ try {
+ injectMocksUsingAnnotationEnabler(target, annotationEnabler);
+ registerProxyFramework();
+ setFrameworkAgentClassRegister();
+ fNext.evaluate();
+ } finally {
+ // Clear the mock repository after each test
+ MockRepository.clear();
+ clearMockFields(target, annotationEnabler);
+ clearFrameworkAgentClassRegister();
+ }
+ }
+
+ private void clearFrameworkAgentClassRegister() {
+ agentClassRegister.clear();
+ javaAgentFrameworkRegister.clear();
+ }
+
+ private void setFrameworkAgentClassRegister() {
+ javaAgentFrameworkRegister.set(agentClassRegister);
+ }
+
+ private Object loadAnnotationEnableIfPresent() {
+ boolean hasAnnotationEnabler = hasAnnotationEnablerClass();
+ if (!hasAnnotationEnabler) {
+ return null;
+ }
+
+ try {
+ return Whitebox.invokeConstructor(Class.forName(ANNOTATION_ENABLER, true, Thread.currentThread().getContextClassLoader()));
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error, failed to load annotation enabler.");
+ }
+ }
+
+ private boolean hasAnnotationEnablerClass() {
+ try {
+ Class.forName(ANNOTATION_ENABLER, false, Thread.currentThread().getContextClassLoader());
+ return true;
+ } catch (ClassNotFoundException e) {
+ return false;
+ }
+ }
+
+ private void clearMockFields(Object target, Object annotationEnabler) throws Exception {
+ if (annotationEnabler != null) {
+ Class<? extends Annotation>[] mockAnnotations = Whitebox.invokeMethod(annotationEnabler, "getMockAnnotations");
+ Set<Field> mockFields = Whitebox.getFieldsAnnotatedWith(target, mockAnnotations);
+ for (Field field : mockFields) {
+ field.set(target, null);
+ }
+ }
+ }
+
+ private void injectMocksUsingAnnotationEnabler(Object target, Object annotationEnabler) throws Exception {
+ if (annotationEnabler != null) {
+ Whitebox.invokeMethod(annotationEnabler, "beforeTestMethod", new Class<?>[]{Object.class, Method.class,
+ Object[].class}, target, null, null);
+ }
+ }
+
+ private static void registerProxyFramework() {
+ ClassLoaderRegisterProxyFramework.registerProxyframework(Thread.currentThread().getContextClassLoader());
+ }
+}
diff --git a/modules/module-impl/junit4-rule/pom.xml b/modules/module-impl/junit4-rule/pom.xml
new file mode 100644
index 0000000..c743a2e
--- /dev/null
+++ b/modules/module-impl/junit4-rule/pom.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock support module for JUnit 4.x rules.
+ </description>
+
+ <profiles>
+ <profile>
+ <id>mockito</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ </profile>
+ <profile>
+ <id>mockito2</id>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock.tests</groupId>
+ <artifactId>powermock-tests-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockClassloaderExecutor.java b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockClassloaderExecutor.java
new file mode 100644
index 0000000..bc11f75
--- /dev/null
+++ b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockClassloaderExecutor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.modules.junit4.rule;
+
+import org.powermock.classloading.SingleClassloaderExecutor;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.impl.ClassMockTransformer;
+import org.powermock.core.transformers.impl.InterfaceMockTransformer;
+import org.powermock.reflect.proxyframework.ClassLoaderRegisterProxyFramework;
+import org.powermock.tests.utils.MockPolicyInitializer;
+import org.powermock.tests.utils.impl.PowerMockIgnorePackagesExtractorImpl;
+import org.powermock.tests.utils.impl.PrepareForTestExtractorImpl;
+import org.powermock.tests.utils.impl.StaticConstructorSuppressExtractorImpl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class PowerMockClassloaderExecutor {
+
+ public static SingleClassloaderExecutor forClass(Class<?> testClass, MockPolicyInitializer mockPolicyInitializer) {
+ List<MockTransformer> mockTransformerChain = new ArrayList<MockTransformer>();
+ mockTransformerChain.add(new ClassMockTransformer());
+ mockTransformerChain.add(new InterfaceMockTransformer());
+
+ MockClassLoader mockLoader = new MockClassLoader(new String[0], new String[0]);
+ mockLoader.setMockTransformerChain(mockTransformerChain);
+
+ mockLoader.addIgnorePackage(new PowerMockIgnorePackagesExtractorImpl().getPackagesToIgnore(testClass));
+ mockLoader.addClassesToModify(new PrepareForTestExtractorImpl().getTestClasses(testClass));
+ mockLoader.addClassesToModify(new StaticConstructorSuppressExtractorImpl().getTestClasses(testClass));
+
+ ClassLoaderRegisterProxyFramework.registerProxyframework(mockLoader);
+
+ mockPolicyInitializer.initialize(mockLoader);
+
+ return new SingleClassloaderExecutor(mockLoader);
+ }
+
+
+}
diff --git a/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java
new file mode 100644
index 0000000..6596823
--- /dev/null
+++ b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRule.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.rule;
+
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.api.support.SafeExceptionRethrower;
+import org.powermock.classloading.ClassloaderExecutor;
+import org.powermock.classloading.SingleClassloaderExecutor;
+import org.powermock.classloading.spi.DoNotClone;
+import org.powermock.core.MockRepository;
+import org.powermock.tests.utils.MockPolicyInitializer;
+import org.powermock.tests.utils.TestChunk;
+import org.powermock.tests.utils.TestSuiteChunker;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+
+public class PowerMockRule implements MethodRule {
+ private static Class<?> previousTargetClass;
+ private static MockPolicyInitializer mockPolicyInitializer;
+
+ @DoNotClone
+ private static TestSuiteChunker testSuiteChunker;
+
+
+ @Override
+ public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+ if (isNotRuleInitialized(target)) {
+ init(target);
+ }
+ return new PowerMockStatement(base, testSuiteChunker.getTestChunk(method.getMethod()), mockPolicyInitializer);
+ }
+
+ protected boolean isNotRuleInitialized(Object target) {return testSuiteChunker == null || previousTargetClass != target.getClass();}
+
+ protected void init(Object target) {
+ final Class<?> testClass = target.getClass();
+
+ try {
+ mockPolicyInitializer = new MockPolicyInitializerImpl(testClass);
+ testSuiteChunker = new PowerMockRuleTestSuiteChunker(testClass);
+ previousTargetClass = target.getClass();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
+
+class PowerMockStatement extends Statement {
+ private final Statement fNext;
+ private final ClassloaderExecutor classloaderExecutor;
+ private final MockPolicyInitializer mockPolicyInitializer;
+
+ public PowerMockStatement(Statement fNext, TestChunk testChunk, MockPolicyInitializer mockPolicyInitializer) {
+ this.fNext = fNext;
+ this.mockPolicyInitializer = mockPolicyInitializer;
+ this.classloaderExecutor = new SingleClassloaderExecutor(testChunk.getClassLoader());
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ classloaderExecutor.execute(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // Re-executes the policy method that might initialize mocks that
+ // were cleared after the previous statement.
+ // This fixes https://github.com/jayway/powermock/issues/581
+ mockPolicyInitializer.refreshPolicies(getClass().getClassLoader());
+ fNext.evaluate();
+ } catch (Throwable e) {
+ SafeExceptionRethrower.safeRethrow(e);
+ } finally {
+ // Clear the mock repository after each test
+ MockRepository.clear();
+ }
+ }
+ });
+ }
+}
diff --git a/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRuleTestSuiteChunker.java b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRuleTestSuiteChunker.java
new file mode 100644
index 0000000..c038af3
--- /dev/null
+++ b/modules/module-impl/junit4-rule/src/main/java/org/powermock/modules/junit4/rule/PowerMockRuleTestSuiteChunker.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.junit4.rule;
+
+import org.powermock.modules.junit4.common.internal.impl.JUnit4TestMethodChecker;
+import org.powermock.tests.utils.impl.AbstractCommonTestSuiteChunkerImpl;
+
+import java.lang.reflect.Method;
+
+/**
+ *
+ */
+public class PowerMockRuleTestSuiteChunker extends AbstractCommonTestSuiteChunkerImpl {
+
+ public PowerMockRuleTestSuiteChunker(Class testClass) throws Exception {
+ super(testClass);
+ }
+
+ @Override
+ public boolean shouldExecuteTestForMethod(Class<?> testClass, Method potentialTestMethod) {
+ return new JUnit4TestMethodChecker(testClass, potentialTestMethod).isTestMethod();
+ }
+
+}
diff --git a/modules/module-impl/junit4/pom.xml b/modules/module-impl/junit4/pom.xml
new file mode 100644
index 0000000..cd8ba80
--- /dev/null
+++ b/modules/module-impl/junit4/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-junit4</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock support module for JUnit 4.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunner.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunner.java
new file mode 100644
index 0000000..3234368
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunner.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+import org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner;
+import org.powermock.modules.junit4.common.internal.impl.JUnitVersion;
+import org.powermock.modules.junit4.internal.impl.DelegatingPowerMockRunner;
+import org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl;
+import org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl;
+import org.powermock.modules.junit4.internal.impl.PowerMockJUnit49RunnerDelegateImpl;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+
+public class PowerMockRunner extends AbstractCommonPowerMockRunner {
+
+ public PowerMockRunner(Class<?> klass) throws Exception {
+ super(klass, getRunnerDelegateImplClass(klass));
+ }
+
+ private static Class<? extends PowerMockJUnitRunnerDelegate> getRunnerDelegateImplClass(Class<?> klass) {
+ if (klass.isAnnotationPresent(PowerMockRunnerDelegate.class)
+ || Boolean.getBoolean("powermock.implicitDelegateAnnotation")) {
+ return DelegatingPowerMockRunner.class;
+ }
+
+ Class<? extends PowerMockJUnitRunnerDelegate> concreteClass = PowerMockJUnit44RunnerDelegateImpl.class;
+ if(JUnitVersion.isGreaterThanOrEqualTo("4.9")) {
+ concreteClass = PowerMockJUnit49RunnerDelegateImpl.class;
+ } else if( JUnitVersion.isGreaterThanOrEqualTo("4.7") ) {
+ concreteClass = PowerMockJUnit47RunnerDelegateImpl.class;
+ }
+ return concreteClass;
+ }
+
+ /**
+ * Clean up some state to avoid OOM issues
+ */
+ @Override
+ public void run(RunNotifier notifier) {
+ Description description = getDescription();
+ try {
+ super.run(notifier);
+ } finally {
+ Whitebox.setInternalState(description, "fAnnotations", new Annotation[]{});
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunnerDelegate.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunnerDelegate.java
new file mode 100644
index 0000000..57cc6fc
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/PowerMockRunnerDelegate.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
+import org.junit.internal.runners.JUnit38ClassRunner;
+import org.junit.internal.runners.JUnit4ClassRunner;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.AllTests;
+import org.junit.runners.JUnit4;
+import org.junit.runners.model.InitializationError;
+import org.junit.runners.model.RunnerBuilder;
+import org.powermock.modules.junit4.common.internal.impl.JUnitVersion;
+
+ at Target(ElementType.TYPE)
+ at Documented
+ at Retention(RetentionPolicy.RUNTIME)
+ at Inherited
+public @interface PowerMockRunnerDelegate {
+
+ Class<? extends Runner> value() default DefaultJUnitRunner.class;
+
+ public final class DefaultJUnitRunner extends Runner {
+
+ private final Runner wrappedDefaultRunner;
+
+ public DefaultJUnitRunner(Class<?> testClass) throws Throwable {
+ wrappedDefaultRunner = createDefaultRunner(testClass);
+ }
+
+ private static Runner createDefaultRunner(Class<?> testClass)
+ throws Throwable {
+ try {
+ Method suiteMethod = testClass.getMethod("suite");
+ if (junit.framework.Test.class.isAssignableFrom(suiteMethod.getReturnType())) {
+ return new AllTests(testClass);
+ } else {
+ /* Continue below ... */
+ }
+ } catch (NoSuchMethodException thereIsNoSuiteMethod) {
+ /* Continue below ... */
+ }
+ if (junit.framework.TestCase.class.isAssignableFrom(testClass)) {
+ return new JUnit38ClassRunner(testClass);
+ } else if (JUnitVersion.isGreaterThanOrEqualTo("4.5")) {
+ return SinceJUnit_4_5.createRunnerDelegate(testClass);
+ } else {
+ return new JUnit4ClassRunner(testClass);
+ }
+ }
+
+ @Override
+ public Description getDescription() {
+ return wrappedDefaultRunner.getDescription();
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ wrappedDefaultRunner.run(notifier);
+ }
+ }
+
+ /**
+ * Stuff that needs to be handled in a separate class, because it
+ * deals with API that did not exist before JUnit-4.5. Having this inside
+ * {@link DefaultJUnitRunner} would cause runtime error when JUnit-4.4
+ * or earlier is used.
+ */
+ public class SinceJUnit_4_5 {
+ static Runner createRunnerDelegate(Class<?> testClass) throws InitializationError {
+ return new JUnit4(testClass);
+ }
+ public static Class[] runnerAlternativeConstructorParams() {
+ return new Class[] {Class.class, RunnerBuilder.class};
+ }
+ public static Object newRunnerBuilder() {
+ return new AllDefaultPossibilitiesBuilder(false);
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/DelegatingPowerMockRunner.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/DelegatingPowerMockRunner.java
new file mode 100644
index 0000000..f7a61bb
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/DelegatingPowerMockRunner.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.junit.Test;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.Filter;
+import org.junit.runner.manipulation.Filterable;
+import org.junit.runner.manipulation.NoTestsRemainException;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.core.testlisteners.GlobalNotificationBuildSupport;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate.SinceJUnit_4_5;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+import org.powermock.modules.junit4.common.internal.impl.JUnitVersion;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+import org.powermock.tests.utils.impl.PowerMockTestNotifierImpl;
+
+public class DelegatingPowerMockRunner extends Runner
+implements PowerMockJUnitRunnerDelegate, Filterable {
+
+ private final String testClassName;
+ private final Runner delegate;
+ private final ClassLoader testClassLoader;
+ private final Method[] testMethods;
+ private final PowerMockTestNotifier powerMockTestNotifier;
+
+ public DelegatingPowerMockRunner(Class<?> klass) throws Throwable {
+ this(klass, null);
+ }
+
+ public DelegatingPowerMockRunner(Class<?> klass, String[] methodsToRun)
+ throws Throwable {
+ this(klass, methodsToRun, null);
+ }
+
+ public DelegatingPowerMockRunner(
+ Class<?> klass, String[] methodsToRun, PowerMockTestListener[] listeners)
+ throws Exception {
+ testClassName = klass.getName();
+ delegate = createDelegate(klass);
+ testClassLoader = klass.getClassLoader();
+ testMethods = determineTestMethods(klass, methodsToRun);
+ powerMockTestNotifier = new PowerMockTestNotifierImpl(listeners == null ? new PowerMockTestListener[0] : listeners);
+ }
+
+ private static Method[] determineTestMethods(
+ Class<?> testClass, String[] testMethodNames) {
+ List<Method> testMethods = new ArrayList<Method>();
+ for (Method m : testClass.getMethods()) {
+ if (m.isAnnotationPresent(Test.class)) {
+ testMethods.add(m);
+ }
+ }
+ if (testMethods.isEmpty()) {
+ for (String testMethodName : testMethodNames) {
+ try {
+ testMethods.add(testClass.getMethod(testMethodName));
+ } catch (NoSuchMethodException ignore) {
+ System.err.println(ignore.getMessage());
+ }
+ }
+ }
+ return testMethods.toArray(new Method[testMethods.size()]);
+ }
+
+ private static Runner createDelegate(final Class<?> testClass)
+ throws Exception {
+ /*
+ * Because of the mockito integration it seems like it is necessary to
+ * set context classloader during delegate creation ...
+ */
+ return withContextClassLoader(testClass.getClassLoader(),
+ new Callable<Runner>() {
+ @Override
+ public Runner call() throws Exception {
+ try {
+ return Whitebox.invokeConstructor(
+ testClass.isAnnotationPresent(PowerMockRunnerDelegate.class)
+ ? testClass.getAnnotation(PowerMockRunnerDelegate.class).value()
+ : PowerMockRunnerDelegate.DefaultJUnitRunner.class,
+ new Class[] {Class.class},
+ new Object[] {testClass});
+ } catch (ConstructorNotFoundException rootProblem) {
+ if (testClass.isAnnotationPresent(PowerMockRunnerDelegate.class)
+ && JUnitVersion.isGreaterThanOrEqualTo("4.5")) {
+ try {
+ return Whitebox.invokeConstructor(testClass.getAnnotation(PowerMockRunnerDelegate.class).value(),
+ SinceJUnit_4_5.runnerAlternativeConstructorParams(),
+ new Object[] {
+ testClass,
+ SinceJUnit_4_5.newRunnerBuilder()
+ });
+ } catch (ConstructorNotFoundException ignoredWorkAroundFailure) {
+ }
+ }
+ throw rootProblem;
+ }
+ }
+ });
+ }
+
+ private static <T> T withContextClassLoader(
+ ClassLoader loader, Callable<T> callable) throws Exception {
+ final ClassLoader originalClassLoaderBackup =
+ Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(loader);
+ return callable.call();
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoaderBackup);
+ }
+ }
+
+ @Override
+ public void run(final RunNotifier notifier) {
+ try {
+ withContextClassLoader(testClassLoader, new Callable<Void>() {
+ @Override
+ public Void call() {
+ PowerMockRunNotifier powerNotifier = new PowerMockRunNotifier(
+ notifier, powerMockTestNotifier, testMethods);
+ try {
+ GlobalNotificationBuildSupport.prepareTestSuite(
+ testClassName, powerNotifier);
+ delegate.run(powerNotifier);
+ } finally {
+ GlobalNotificationBuildSupport
+ .closePendingTestSuites(powerNotifier);
+ }
+ return null;
+ }
+ });
+ } catch (Exception cannotHappen) {
+ throw new Error(cannotHappen);
+ }
+ }
+
+ @Override
+ public Description getDescription() {
+ return delegate.getDescription();
+ }
+
+ @Override
+ public int getTestCount() {
+ return delegate.testCount();
+ }
+
+ @Override
+ public Class<?> getTestClass() {
+ return getDescription().getTestClass();
+ }
+
+ @Override
+ public void filter(Filter filter) throws NoTestsRemainException {
+ if (this.delegate instanceof Filterable) {
+ ((Filterable) this.delegate).filter(filter);
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/NotificationBuilder.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/NotificationBuilder.java
new file mode 100644
index 0000000..db50c57
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/NotificationBuilder.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.IdentityHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.junit.runner.Description;
+import org.junit.runner.notification.Failure;
+import org.powermock.core.spi.testresult.Result;
+import org.powermock.core.spi.testresult.TestMethodResult;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+
+/**
+ * Stateful class that, from information from JUnit and test-classes,
+ * can build and send notifications to PowerMockTestNotifier.
+ */
+class NotificationBuilder {
+
+ enum DetectedTestRunBehaviour {
+ PENDING,
+ START_FIRES_FIRST,
+ TEST_INSTANCE_CREATED_FIRST,
+ ALL_TESTINSTANCES_ARE_CREATED_FIRST,
+ TEST_INSTANCES_ARE_REUSED,
+ INCONSISTENT_BEHAVIOUR;
+ }
+
+ private static final Pattern methodDisplayNameRgx =
+ Pattern.compile("^[^\\(\\[]++");
+ private final Method[] testMethods;
+ private final List<?> pendingTestInstances;
+ private final PowerMockTestNotifier powerMockTestNotifier;
+ private DetectedTestRunBehaviour behaviour = DetectedTestRunBehaviour.PENDING;
+ private Description currentDescription;
+ private Object currentTestInstance;
+ private String testClassName;
+
+ private Object latestTestInstance;
+ private Method latestMethod;
+ private static final Object[] unsupportedMethodArgs = {};
+
+ private final Map<Object, List<Method>> methodsPerInstance =
+ new IdentityHashMap<Object, List<Method>>() {
+ @Override
+ public List<Method> get(Object key) {
+ if (false == containsKey(key)) {
+ put(key, new LinkedList<Method>());
+ }
+ return super.get(key);
+ }
+ };
+
+ private final Map<Description, OngoingTestRun> ongoingTestRuns =
+ new IdentityHashMap<Description, OngoingTestRun>();
+
+ private class OngoingTestRun implements TestMethodResult {
+ final Description testDescription;
+ final Object testInstance;
+ final Method testMethod;
+ private Result result;
+
+ OngoingTestRun(Description testDescription, Object testInstance) {
+ this.testDescription = testDescription;
+ this.testInstance = testInstance;
+ this.testMethod = determineTestMethod(testDescription);
+ pendingTestInstances.remove(testInstance);
+ Class<?> testClass = testClass();
+ new MockPolicyInitializerImpl(testClass).initialize(testClass.getClassLoader());
+ powerMockTestNotifier.notifyBeforeTestMethod(
+ testInstance, testMethod, unsupportedMethodArgs);
+ ongoingTestRuns.put(testDescription, this);
+ }
+
+ final Class<?> testClass() {
+ if (null == testClassName) {
+ return testInstance.getClass();
+ } else {
+ try {
+ return Class.forName(testClassName, false,
+ testInstance.getClass().getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ return testInstance.getClass();
+ }
+ }
+ }
+
+ void report(Result result) {
+ if (null != this.result && Result.SUCCESSFUL == result
+ || this.result == result) {
+ /* Already notified - ignore this duplication */
+ return;
+
+ } else if (null != this.result) {
+ new IllegalStateException(
+ "Will report an unexpected result-notification " + result
+ + " after previously received notification " + this.result)
+ .printStackTrace();
+ }
+ this.result = result;
+ powerMockTestNotifier.notifyAfterTestMethod(
+ testInstance, testMethod, unsupportedMethodArgs, this);
+ }
+
+ @Override
+ public Result getResult() {
+ return this.result;
+ }
+ }
+
+ public NotificationBuilder(Method[] testMethods,
+ PowerMockTestNotifier notifier,
+ List<?> pendingTestInstances) {
+ this.testMethods = testMethods;
+ this.pendingTestInstances = pendingTestInstances;
+ this.powerMockTestNotifier = notifier;
+ }
+
+ private Method determineTestMethod(Description d) {
+ Matcher matchMethodName = methodDisplayNameRgx
+ .matcher(d.getDisplayName());
+ matchMethodName.find();
+ String methodName = matchMethodName.group();
+ boolean latestTestMethodCanBeRepeated = false;
+ for (Method m : testMethods) {
+ if (m.getName().equals(methodName)) {
+ if (m == latestMethod) {
+ latestTestMethodCanBeRepeated = true;
+ } else {
+ return latestMethod = m;
+ }
+ }
+ }
+ if (latestTestMethodCanBeRepeated) {
+ return latestMethod;
+ } else {
+ new IllegalArgumentException(
+ "Unable to determine method-name from description="
+ + d + "; - ignored").printStackTrace();
+ return null;
+ }
+ }
+
+ private Class<?> reloadParamType(
+ Class<?> testClass, Class<?> typeToReload) {
+ if (typeToReload.isPrimitive()
+ || testClass.getClassLoader() == typeToReload.getClassLoader()) {
+ return typeToReload;
+
+ } else if (typeToReload.isArray()) {
+ Class<?> newComponentType = reloadParamType(
+ testClass, typeToReload.getComponentType());
+ if (newComponentType == typeToReload.getComponentType()) {
+ return typeToReload;
+ } else {
+ return Array.newInstance(newComponentType, 0).getClass();
+ }
+
+ } else {
+ try {
+ return Class.forName(typeToReload.getName(),
+ true, testClass.getClassLoader());
+ } catch (ClassNotFoundException ex) {
+ throw new Error(ex);
+ }
+ }
+ }
+
+ private Method reloadMethod(Class<?> testClass, Method m) {
+ if (testClass.getClassLoader() == m.getDeclaringClass().getClassLoader()) {
+ return m;
+ } else if (false == m.getDeclaringClass().getName()
+ .equals(testClass.getName())) {
+ return reloadMethod(testClass.getSuperclass(), m);
+ }
+ Class[] paramTypes = m.getParameterTypes();
+ for (int i = 0; i < paramTypes.length; ++i) {
+ paramTypes[i] = reloadParamType(testClass, paramTypes[i]);
+ }
+ try {
+ return testClass.getDeclaredMethod(m.getName(), paramTypes);
+ } catch (NoSuchMethodException ex) {
+ throw new Error(ex);
+ }
+ }
+
+ void testSuiteStarted(Class<?> testClass) {
+ for (int i = 0; i < testMethods.length; ++i) {
+ testMethods[i] = reloadMethod(testClass, testMethods[i]);
+ }
+ powerMockTestNotifier.notifyBeforeTestSuiteStarted(testClass, testMethods);
+ this.testClassName = testClass.getName();
+ }
+
+ void testStartHasBeenFired(Description d) {
+ OngoingTestRun oldTestRun = ongoingTestRuns.get(d);
+ if (null != oldTestRun && null != oldTestRun.getResult()) {
+ throw new IllegalStateException(
+ "Fired testrun is already running: " + d);
+ }
+ currentDescription = d;
+ switch (behaviour) {
+ case PENDING:
+ behaviour = DetectedTestRunBehaviour.START_FIRES_FIRST;
+ case START_FIRES_FIRST:
+ return;
+ case TEST_INSTANCE_CREATED_FIRST:
+ if (currentTestInstance == latestTestInstance) {
+ behaviour = DetectedTestRunBehaviour.TEST_INSTANCES_ARE_REUSED;
+ }
+ case TEST_INSTANCES_ARE_REUSED:
+ latestTestInstance = currentTestInstance;
+ methodsPerInstance.get(currentTestInstance).add(
+ new OngoingTestRun(d, currentTestInstance).testMethod);
+ return;
+ case ALL_TESTINSTANCES_ARE_CREATED_FIRST:
+ System.err.println(
+ "Notifications are not supported when all test-instances are created first!");
+ return;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ void testInstanceCreated(Object newTestInstance) {
+ switch (behaviour) {
+ case PENDING:
+ behaviour = DetectedTestRunBehaviour.TEST_INSTANCE_CREATED_FIRST;
+ currentTestInstance = newTestInstance;
+ return ;
+ case TEST_INSTANCE_CREATED_FIRST:
+ if (methodsPerInstance.isEmpty()) {
+ behaviour = DetectedTestRunBehaviour.ALL_TESTINSTANCES_ARE_CREATED_FIRST;
+ } else if (currentTestInstance == latestTestInstance) {
+ currentTestInstance = newTestInstance;
+ } else {
+ behaviour = DetectedTestRunBehaviour.INCONSISTENT_BEHAVIOUR;
+ }
+ return;
+ case ALL_TESTINSTANCES_ARE_CREATED_FIRST:
+ case INCONSISTENT_BEHAVIOUR:
+ System.err.println(
+ "Notifications are not supported for behaviour " + behaviour);
+ return;
+ case START_FIRES_FIRST:
+ currentTestInstance = latestTestInstance = newTestInstance;
+ latestMethod = determineTestMethod(currentDescription);
+ methodsPerInstance.get(newTestInstance).add(
+ new OngoingTestRun(currentDescription, newTestInstance).testMethod);
+ return;
+ default:
+ throw new AssertionError("Unknown behaviour: " + behaviour);
+ }
+ }
+
+ void testIgnored(Description d) {
+ if (false == notify(d, Result.IGNORED)
+ && DetectedTestRunBehaviour.TEST_INSTANCE_CREATED_FIRST == behaviour
+ && currentTestInstance != latestTestInstance) {
+ /*
+ * Workaround for some bad behaviour in JUnit-4.4 default runner,
+ * which creates a test-instance first, even for a test that is ignored!!
+ */
+ currentTestInstance = latestTestInstance;
+ }
+ }
+
+ void assumptionFailed(Description d) {
+ notify(d, Result.IGNORED);
+ }
+
+ void failure(Failure f) {
+ notify(f.getDescription(), Result.FAILED);
+ }
+
+ void testFinished(Description d) {
+ notify(d, Result.SUCCESSFUL);
+ }
+
+ /**
+ * @return true if notification concerns an ongoing testrun; otherwise false
+ * when there is no test launched for the specified description
+ */
+ private boolean notify(Description d, Result result) {
+ OngoingTestRun testRun = ongoingTestRuns.get(d);
+ if (null == testRun) {
+// System.err.println("Notification not enabled for " + d);
+ return false;
+ } else {
+ testRun.report(result);
+ return true;
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit44RunnerDelegateImpl.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit44RunnerDelegateImpl.java
new file mode 100644
index 0000000..037f02c
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit44RunnerDelegateImpl.java
@@ -0,0 +1,383 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.junit.Before;
+import org.junit.internal.runners.*;
+import org.junit.runner.Description;
+import org.junit.runner.Runner;
+import org.junit.runner.manipulation.*;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.classloader.annotations.PrepareEverythingForTest;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.modules.junit4.common.internal.PowerMockJUnitRunnerDelegate;
+import org.powermock.modules.junit4.internal.impl.testcaseworkaround.PowerMockJUnit4MethodValidator;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+import org.powermock.tests.utils.impl.PowerMockTestNotifierImpl;
+import org.powermock.tests.utils.impl.PrepareForTestExtractorImpl;
+import org.powermock.tests.utils.impl.StaticConstructorSuppressExtractorImpl;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
+/**
+ * A JUnit4 test runner that only runs a specified set of test methods in a test
+ * class.
+ * <p/>
+ * <p/>
+ * Many parts of this class are essentially a rip off from
+ * {@link JUnit4ClassRunner} used in JUnit 4.4. It does however not extend this
+ * class because we cannot let it perform the stuff it does in its constructor.
+ * Another thing that different is that if an exception is thrown in the test we
+ * add a tip to error message asking the user if they've not forgot to add a
+ * class to test. Yet another difference is that this runner notifies the
+ * PowerMock listeners of certain events.
+ *
+ * @see JUnit4ClassRunner
+ */
+ at SuppressWarnings("deprecation")
+public class PowerMockJUnit44RunnerDelegateImpl extends Runner implements Filterable, Sortable, PowerMockJUnitRunnerDelegate {
+ private final List<Method> testMethods;
+ private final TestClass testClass;
+ private final PowerMockTestNotifier powerMockTestNotifier;
+
+ public PowerMockJUnit44RunnerDelegateImpl(Class<?> klass, String[] methodsToRun, PowerMockTestListener[] listeners) throws InitializationError {
+ this.powerMockTestNotifier = new PowerMockTestNotifierImpl(listeners == null ? new PowerMockTestListener[0] : listeners);
+ testClass = new TestClass(klass);
+ testMethods = getTestMethods(klass, methodsToRun);
+ validate();
+ }
+
+ public PowerMockJUnit44RunnerDelegateImpl(Class<?> klass, String[] methodsToRun) throws InitializationError {
+ this(klass, methodsToRun, null);
+ }
+
+ public PowerMockJUnit44RunnerDelegateImpl(Class<?> klass) throws InitializationError {
+ this(klass, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected final List<Method> getTestMethods(Class<?> klass, String[] methodsToRun) {
+ if (methodsToRun == null || methodsToRun.length == 0) {
+ // The getTestMethods of TestClass is not visible so we need to look
+ // it invoke it using reflection.
+ try {
+ return (List<Method>) Whitebox.invokeMethod(testClass, "getTestMethods");
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ }
+ } else {
+ List<Method> foundMethods = new LinkedList<Method>();
+ Method[] methods = klass.getMethods();
+ for (Method method : methods) {
+ for (String methodName : methodsToRun) {
+ if (method.getName().equals(methodName)) {
+ foundMethods.add(method);
+ }
+ }
+ }
+ return foundMethods;
+ }
+ }
+
+ protected final void validate() throws InitializationError {
+ if (!TestCase.class.isAssignableFrom(testClass.getJavaClass())) {
+ MethodValidator methodValidator = new PowerMockJUnit4MethodValidator(testClass);
+ methodValidator.validateMethodsForDefaultRunner();
+ methodValidator.assertValid();
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void run(final RunNotifier notifier) {
+ new ClassRoadie(notifier, testClass, getDescription(), new Runnable() {
+ @Override
+ public void run() {
+ runMethods(notifier);
+ }
+ }).runProtected();
+ }
+
+ protected void runMethods(final RunNotifier notifier) {
+ final StaticConstructorSuppressExtractorImpl staticConstructorSuppressExtractorImpl = new StaticConstructorSuppressExtractorImpl();
+ Class<?> testType = getTestClass();
+ final ClassLoader thisClassLoader = getClass().getClassLoader();
+ if (!thisClassLoader.equals(testType.getClassLoader())) {
+ /*
+ * The test is loaded from another classloader, this means that we
+ * cannot get the correct annotations if we don't load the class
+ * from the correct class loader
+ */
+ try {
+ testType = thisClassLoader.loadClass(testType.getName());
+ } catch (ClassNotFoundException e) {
+ // This should never happen
+ throw new RuntimeException("Internal error in PowerMock", e);
+ }
+ }
+ for (Method method : testMethods) {
+ if (staticConstructorSuppressExtractorImpl.getTestClasses(method) == null) {
+ staticConstructorSuppressExtractorImpl.getTestClasses(testType);
+ }
+ invokeTestMethod(method, notifier);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Description getDescription() {
+ Description spec = Description.createSuiteDescription(getName(), classAnnotations());
+ List<Method> testMethods = this.testMethods;
+ for (Method method : testMethods)
+ spec.addChild(methodDescription(method));
+ return spec;
+ }
+
+ protected Annotation[] classAnnotations() {
+ return getTestClass().getAnnotations();
+ }
+
+ protected String getName() {
+ return getTestWrappedClass().getName();
+ }
+
+ protected Object createTest() throws Exception {
+ return createTestInstance();
+ }
+
+ private Object createTestInstance() throws InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+ final TestClass testWrappedClass = getTestWrappedClass();
+ Constructor<?> constructor = null;
+ final Class<?> javaClass = testWrappedClass.getJavaClass();
+ if (TestCase.class.isAssignableFrom(javaClass)) {
+ constructor = TestSuite.getTestConstructor(javaClass.asSubclass(TestCase.class));
+ if (constructor.getParameterTypes().length == 1) {
+ return constructor.newInstance(javaClass.getSimpleName());
+ }
+ } else {
+ constructor = testWrappedClass.getConstructor();
+ }
+ return constructor.newInstance();
+ }
+
+ protected void invokeTestMethod(final Method method, RunNotifier notifier) {
+ Description description = methodDescription(method);
+ final Object testInstance;
+ try {
+ testInstance = createTest();
+ } catch (InvocationTargetException e) {
+ testAborted(notifier, description, e.getTargetException());
+ return;
+ } catch (Exception e) {
+ testAborted(notifier, description, e);
+ return;
+ }
+
+ // Check if we extend from TestClass, in that case we must run the setUp
+ // and tearDown methods.
+ final boolean extendsFromTestCase = TestCase.class.isAssignableFrom(testClass.getJavaClass()) ? true : false;
+
+ final TestMethod testMethod = wrapMethod(method);
+ createPowerMockRunner(testInstance, testMethod, notifier, description, extendsFromTestCase).run();
+ }
+
+ protected PowerMockJUnit44MethodRunner createPowerMockRunner(final Object testInstance, final TestMethod testMethod, RunNotifier notifier,
+ Description description, final boolean extendsFromTestCase) {
+ return new PowerMockJUnit44MethodRunner(testInstance, testMethod, notifier, description, extendsFromTestCase);
+ }
+
+ private void testAborted(RunNotifier notifier, Description description, Throwable e) {
+ notifier.fireTestStarted(description);
+ notifier.fireTestFailure(new Failure(description, e));
+ notifier.fireTestFinished(description);
+ }
+
+ protected TestMethod wrapMethod(Method method) {
+ return new TestMethod(method, testClass);
+ }
+
+ protected String testName(Method method) {
+ return method.getName();
+ }
+
+ protected Description methodDescription(Method method) {
+ return Description.createTestDescription(getTestWrappedClass().getJavaClass(), testName(method), testAnnotations(method));
+ }
+
+ protected Annotation[] testAnnotations(Method method) {
+ return method.getAnnotations();
+ }
+
+ @Override
+ public void filter(Filter filter) throws NoTestsRemainException {
+ for (Iterator<Method> iter = testMethods.iterator(); iter.hasNext(); ) {
+ Method method = iter.next();
+ if (!filter.shouldRun(methodDescription(method)))
+ iter.remove();
+ }
+ if (testMethods.isEmpty())
+ throw new NoTestsRemainException();
+ }
+
+ @Override
+ public void sort(final Sorter sorter) {
+ Collections.sort(testMethods, new Comparator<Method>() {
+ @Override
+ public int compare(Method o1, Method o2) {
+ return sorter.compare(methodDescription(o1), methodDescription(o2));
+ }
+ });
+ }
+
+ protected TestClass getTestWrappedClass() {
+ return testClass;
+ }
+
+ @Override
+ public int getTestCount() {
+ return testMethods.size();
+ }
+
+ @Override
+ public Class<?> getTestClass() {
+ return testClass.getJavaClass();
+ }
+
+ protected class PowerMockJUnit44MethodRunner extends MethodRoadie {
+ private final Object testInstance;
+ private final boolean extendsFromTestCase;
+ protected final TestMethod testMethod;
+
+ protected PowerMockJUnit44MethodRunner(Object testInstance, TestMethod method, RunNotifier notifier, Description description,
+ boolean extendsFromTestCase) {
+ super(testInstance, method, notifier, description);
+ this.testInstance = testInstance;
+ this.extendsFromTestCase = extendsFromTestCase;
+ this.testMethod = method;
+ }
+
+ @Override
+ public void runBeforesThenTestThenAfters(final Runnable test) {
+ executeTest(Whitebox.getInternalState(testMethod, Method.class), testInstance, test);
+ }
+
+ public void executeTest(final Method method, final Object testInstance, final Runnable test) {
+ // Initialize mock policies for each test
+ final ClassLoader classloader = this.getClass().getClassLoader();
+ final Thread currentThread = Thread.currentThread();
+ final ClassLoader originalClassLoader = currentThread.getContextClassLoader();
+ currentThread.setContextClassLoader(classloader);
+ new MockPolicyInitializerImpl(testClass.getJavaClass()).initialize(classloader);
+ powerMockTestNotifier.notifyBeforeTestMethod(testInstance, method, new Object[0]);
+ try {
+ super.runBeforesThenTestThenAfters(test);
+ } finally {
+ currentThread.setContextClassLoader(originalClassLoader);
+ }
+ }
+
+ @Override
+ protected void runTestMethod() {
+ try {
+ try {
+ if (extendsFromTestCase) {
+ final Method setUp = Whitebox.getMethod(testInstance.getClass(), "setUp");
+ if (!setUp.isAnnotationPresent(Before.class)) {
+ Whitebox.invokeMethod(testInstance, "setUp");
+ }
+ }
+ testMethod.invoke(testInstance);
+ if ((Boolean) Whitebox.invokeMethod(testMethod, "expectsException")) {
+ addFailure(new AssertionError("Expected exception: " + getExpectedExceptionName(testMethod)));
+ }
+ } catch (InvocationTargetException e) {
+ handleInvocationTargetException(testMethod, e);
+ } catch (Throwable e) {
+ addFailure(e);
+ } finally {
+ if (extendsFromTestCase) {
+ try {
+ Whitebox.invokeMethod(testInstance, "tearDown");
+ } catch (Throwable tearingDown) {
+ addFailure(tearingDown);
+ }
+ }
+ }
+ } catch (Throwable e) {
+ throw new RuntimeException("Internal error in PowerMock.", e);
+ }
+ }
+
+ private void handleInvocationTargetException(final TestMethod testMethod, InvocationTargetException e) throws Exception {
+ Throwable actual = e.getTargetException();
+ while (actual instanceof InvocationTargetException) {
+ actual = ((InvocationTargetException) actual).getTargetException();
+ }
+ handleException(testMethod, actual);
+ }
+
+ protected void handleException(final TestMethod testMethod, Throwable actualFailure) {
+ try {
+ final String throwableName = actualFailure.getClass().getName();
+ if (throwableName.equals("org.junit.internal.AssumptionViolatedException") || throwableName.startsWith("org.junit.Assume$AssumptionViolatedException")) {
+ return;
+ } else if (!(Boolean) Whitebox.invokeMethod(testMethod, "expectsException")) {
+ final String className = actualFailure.getStackTrace()[0].getClassName();
+ final Class<?> testClassAsJavaClass = testClass.getJavaClass();
+ if (actualFailure instanceof NullPointerException
+ && !testClassAsJavaClass.getName().equals(className)
+ && !className.startsWith("java.lang")
+ && !className.startsWith("org.powermock")
+ && !className.startsWith("org.junit")
+ && !new PrepareForTestExtractorImpl().isPrepared(testClassAsJavaClass, className)
+ && !testClassAsJavaClass.isAnnotationPresent(PrepareEverythingForTest.class)
+ && !new MockPolicyInitializerImpl(testClassAsJavaClass.isAnnotationPresent(MockPolicy.class) ? testClassAsJavaClass
+ .getAnnotation(MockPolicy.class).value() : null).isPrepared(className)) {
+ Whitebox.setInternalState(actualFailure, "detailMessage", "Perhaps the class " + className + " must be prepared for test?",
+ Throwable.class);
+ }
+ addFailure(actualFailure);
+ } else if ((Boolean) Whitebox.invokeMethod(testMethod, "isUnexpected", actualFailure)) {
+ String message = "Unexpected exception, expected<" + getExpectedExceptionName(testMethod) + "> but was<"
+ + actualFailure.getClass().getName() + ">";
+ addFailure(new Exception(message, actualFailure));
+ }
+
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error: Should never throw exception at this level", e);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private String getExpectedExceptionName(TestMethod fTestMethod) throws Exception {
+ return ((Class<? extends Throwable>) Whitebox.invokeMethod(fTestMethod, "getExpectedException")).getName();
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit47RunnerDelegateImpl.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit47RunnerDelegateImpl.java
new file mode 100644
index 0000000..030dded
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit47RunnerDelegateImpl.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import org.junit.Rule;
+import org.junit.internal.runners.InitializationError;
+import org.junit.internal.runners.TestMethod;
+import org.junit.rules.MethodRule;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Extends the functionality of {@link PowerMockJUnit44RunnerDelegateImpl} to
+ * enable the usage of rules.
+ */
+ at SuppressWarnings("deprecation")
+public class PowerMockJUnit47RunnerDelegateImpl extends PowerMockJUnit44RunnerDelegateImpl {
+ public boolean hasRules;
+
+ public PowerMockJUnit47RunnerDelegateImpl(Class<?> klass, String[] methodsToRun, PowerMockTestListener[] listeners) throws InitializationError {
+ super(klass, methodsToRun, listeners);
+ }
+
+ public PowerMockJUnit47RunnerDelegateImpl(Class<?> klass, String[] methodsToRun) throws InitializationError {
+ super(klass, methodsToRun);
+ }
+
+ public PowerMockJUnit47RunnerDelegateImpl(Class<?> klass) throws InitializationError {
+ super(klass);
+ }
+
+ @Override
+ protected PowerMockJUnit44MethodRunner createPowerMockRunner(final Object testInstance, final TestMethod testMethod, RunNotifier notifier,
+ Description description, final boolean extendsFromTestCase) {
+ return new PowerMockJUnit47MethodRunner(testInstance, testMethod, notifier, description, extendsFromTestCase);
+ }
+
+ protected class PowerMockJUnit47MethodRunner extends PowerMockJUnit44MethodRunner {
+
+ private Throwable potentialTestFailure;
+
+ protected PowerMockJUnit47MethodRunner(Object testInstance, TestMethod method, RunNotifier notifier, Description description,
+ boolean extendsFromTestCase) {
+ super(testInstance, method, notifier, description, extendsFromTestCase);
+ }
+
+ @Override
+ public void executeTest(final Method method, final Object testInstance, final Runnable test) {
+ // We change the context classloader to the current CL in order for the Mockito
+ // framework to load it's plugins (such as MockMaker) correctly.
+ final ClassLoader originalCL = Thread.currentThread().getContextClassLoader();
+ Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
+ final Set<Field> rules;
+ try {
+ rules = Whitebox.getFieldsAnnotatedWith( testInstance, Rule.class );
+ } finally {
+ Thread.currentThread().setContextClassLoader(originalCL);
+ }
+ hasRules = !rules.isEmpty();
+ Statement statement = createStatement(method, testInstance, test, rules);
+ evaluateStatement(statement);
+ }
+
+ private Statement createStatement(Method method, Object testInstance, Runnable test, Set<Field> rules) {
+ Statement statement = new TestExecutorStatement(test, testInstance, method);
+ for (Field field : rules) {
+ try {
+ statement = applyRuleToLastStatement(method,
+ testInstance, field, statement);
+ } catch (Throwable e) {
+ super.handleException(testMethod, e);
+ }
+ }
+ return statement;
+ }
+
+ protected Statement applyRuleToLastStatement(final Method method, final Object testInstance, Field field,
+ final Statement lastStatement) throws IllegalAccessException {
+ MethodRule rule = (MethodRule) field.get(testInstance);
+ Statement statement = rule.apply(lastStatement, new FrameworkMethod(method), testInstance);
+ return statement;
+ }
+
+ private void evaluateStatement(Statement statement) {
+ try {
+ statement.evaluate();
+ } catch (Throwable e) {
+ //No rule could handle the exception thus we need to add it as a failure.
+ super.handleException(testMethod, potentialTestFailure == null ? e : potentialTestFailure);
+ }
+ }
+
+ /**
+ * Since a JUnit 4.7 rule may potentially deal with "unexpected"
+ * exceptions we cannot handle the exception before the rule has been
+ * completely evaluated. Thus we just store the exception here and
+ * rethrow it after the test method has finished executing. In that way
+ * the rule may get a chance to handle the exception appropriately.
+ */
+ @Override
+ protected void handleException(TestMethod testMethod, Throwable actualFailure) {
+ if (hasRules) {
+ potentialTestFailure = actualFailure;
+ } else {
+ super.handleException(testMethod, actualFailure);
+ }
+ }
+
+ private void executeTestInSuper(final Method method, final Object testInstance, final Runnable test) {
+ super.executeTest(method, testInstance, test);
+ }
+
+ private final class TestExecutorStatement extends Statement {
+ private final Runnable test;
+ private final Object testInstance;
+ private final Method method;
+
+ private TestExecutorStatement(Runnable test, Object testInstance, Method method) {
+ this.test = test;
+ this.testInstance = testInstance;
+ this.method = method;
+ }
+
+ @Override
+ public void evaluate() throws Throwable {
+ executeTestInSuper(method, testInstance, test);
+ if (potentialTestFailure != null) {
+ // Rethrow the potential failure caught in the test.
+ throw potentialTestFailure;
+ }
+ }
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit49RunnerDelegateImpl.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit49RunnerDelegateImpl.java
new file mode 100644
index 0000000..6b14d73
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockJUnit49RunnerDelegateImpl.java
@@ -0,0 +1,75 @@
+package org.powermock.modules.junit4.internal.impl;
+
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import org.junit.internal.runners.InitializationError;
+import org.junit.internal.runners.TestMethod;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.model.Statement;
+import org.powermock.core.spi.PowerMockTestListener;
+
+
+/**
+ * Extends the functionality of {@link PowerMockJUnit47RunnerDelegateImpl} to enable the usage of
+ * {@link TestRule}.
+ */
+ at SuppressWarnings( "deprecation" )
+public class PowerMockJUnit49RunnerDelegateImpl extends PowerMockJUnit47RunnerDelegateImpl {
+
+ public PowerMockJUnit49RunnerDelegateImpl( Class<?> klass, String[] methodsToRun, PowerMockTestListener[] listeners ) throws InitializationError {
+ super( klass, methodsToRun, listeners );
+ }
+
+ public PowerMockJUnit49RunnerDelegateImpl( Class<?> klass, String[] methodsToRun ) throws InitializationError {
+ super( klass, methodsToRun );
+ }
+
+ public PowerMockJUnit49RunnerDelegateImpl( Class<?> klass ) throws InitializationError {
+ super( klass );
+ }
+
+ @Override
+ protected PowerMockJUnit47MethodRunner createPowerMockRunner( final Object testInstance,
+ final TestMethod testMethod,
+ RunNotifier notifier,
+ Description description,
+ final boolean extendsFromTestCase ) {
+ return new PowerMockJUnit49MethodRunner( testInstance, testMethod, notifier, description, extendsFromTestCase );
+ }
+
+ protected class PowerMockJUnit49MethodRunner extends PowerMockJUnit47MethodRunner {
+
+ private Description description;
+
+ protected PowerMockJUnit49MethodRunner( Object testInstance,
+ TestMethod method,
+ RunNotifier notifier,
+ Description description,
+ boolean extendsFromTestCase ) {
+ super( testInstance, method, notifier, description, extendsFromTestCase );
+ this.description = description;
+ }
+
+ @Override
+ protected Statement applyRuleToLastStatement(final Method method, final Object testInstance, Field field,
+ final Statement lastStatement) throws IllegalAccessException {
+ final Object fieldValue = field.get(testInstance);
+ final Statement statement;
+ if (fieldValue instanceof MethodRule) {
+ // the MethodRule is known by junit 4.9 -> delegate to super-class
+ statement = super.applyRuleToLastStatement(method, testInstance, field, lastStatement);
+ } else if (fieldValue instanceof TestRule){
+ TestRule rule = (TestRule) fieldValue;
+ statement = rule.apply(lastStatement, description);
+ } else {
+ throw new IllegalStateException("Can only handle MethodRule and TestRule");
+ }
+ return statement;
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifier.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifier.java
new file mode 100644
index 0000000..74fc8d2
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifier.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runner.notification.StoppedByUserException;
+import org.powermock.core.spi.PowerMockTestListener;
+import org.powermock.core.testlisteners.GlobalNotificationBuildSupport;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+
+import static org.powermock.reflect.Whitebox.invokeMethod;
+
+/**
+ * Wraps JUnit's RunNotifier to make sure that the PowerMock-specific
+ * instances of {@link PowerMockTestListener} will also be informed.
+ * It is stateful and (hopefully) thread-safe.
+ *
+ * @see PowerMockTestListener
+ */
+class PowerMockRunNotifier extends RunNotifier
+implements GlobalNotificationBuildSupport.Callback {
+
+ private Class<?> suiteClass = null;
+ private final Thread motherThread = Thread.currentThread();
+ private final RunNotifier junitRunNotifier;
+ private final PowerMockTestNotifier powerMockTestNotifier;
+ private final Method[] testMethods;
+ private final LinkedList<Object> pendingTestInstancesOnMotherThread =
+ new LinkedList<Object>();
+ private final ThreadLocal<NotificationBuilder> notificationBuilder =
+ new ThreadLocal<NotificationBuilder>() {
+ @Override
+ protected NotificationBuilder initialValue() {
+ return new NotificationBuilder(
+ (Method[]) testMethods.clone(),
+ powerMockTestNotifier,
+ pendingTestInstancesOnMotherThread);
+ }
+ };
+
+ PowerMockRunNotifier(
+ RunNotifier junitRunNotifier,
+ PowerMockTestNotifier powerMockTestNotifier,
+ Method[] testMethods) {
+ this.junitRunNotifier = junitRunNotifier;
+ this.powerMockTestNotifier = powerMockTestNotifier;
+ this.testMethods = testMethods;
+ }
+
+ Class<?> getSuiteClass() {
+ return this.suiteClass;
+ }
+
+ @Override
+ public void suiteClassInitiated(Class<?> testClass) {
+ this.suiteClass = testClass;
+ notificationBuilder.get().testSuiteStarted(testClass);
+ }
+
+ @Override
+ public void testInstanceCreated(Object testInstance) {
+ if (Thread.currentThread() == motherThread) {
+ pendingTestInstancesOnMotherThread.add(testInstance);
+ }
+ notificationBuilder.get().testInstanceCreated(testInstance);
+ }
+
+ @Override
+ public void addListener(RunListener listener) {
+ invoke("addListener", listener);
+ }
+
+ @Override
+ public void removeListener(RunListener listener) {
+ invoke("removeListener", listener);
+ }
+
+ @Override
+ public void fireTestRunStarted(Description description) {
+ invoke("fireTestRunStarted", description);
+ }
+
+ @Override
+ public void fireTestRunFinished(Result result) {
+ invoke("fireTestRunFinished", result);
+ }
+
+ @Override
+ public void fireTestStarted(Description description)
+ throws StoppedByUserException {
+ invoke("fireTestStarted", description);
+ notificationBuilder.get().testStartHasBeenFired(description);
+ }
+
+ @Override
+ public void fireTestFailure(Failure failure) {
+ notificationBuilder.get().failure(failure);
+ invoke("fireTestFailure", failure);
+ }
+
+ @Override
+ public void fireTestAssumptionFailed(Failure failure) {
+ notificationBuilder.get().assumptionFailed(failure.getDescription());
+ invoke("fireTestAssumptionFailed", failure);
+ }
+
+ @Override
+ public void fireTestIgnored(Description description) {
+ notificationBuilder.get().testIgnored(description);
+ invoke("fireTestIgnored", description);
+ }
+
+ @Override
+ public void fireTestFinished(Description description) {
+ try {
+ notificationBuilder.get().testFinished(description);
+ } catch (Throwable failure) {
+ fireTestFailure(new Failure(description, failure));
+ return;
+ }
+ invoke("fireTestFinished", description);
+ }
+
+ @Override
+ public void pleaseStop() {
+ invoke("pleaseStop");
+ }
+
+ @Override
+ public void addFirstListener(RunListener listener) {
+ invoke("addFirstListener", listener);
+ }
+
+ private void invoke(String methodName, Object... args) {
+ try {
+ invokeMethod(junitRunNotifier, methodName, args);
+ } catch (Exception ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+}
diff --git a/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/testcaseworkaround/PowerMockJUnit4MethodValidator.java b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/testcaseworkaround/PowerMockJUnit4MethodValidator.java
new file mode 100644
index 0000000..3d3d583
--- /dev/null
+++ b/modules/module-impl/junit4/src/main/java/org/powermock/modules/junit4/internal/impl/testcaseworkaround/PowerMockJUnit4MethodValidator.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl.testcaseworkaround;
+
+import junit.framework.TestCase;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.internal.runners.MethodValidator;
+import org.junit.internal.runners.TestClass;
+import org.powermock.modules.junit4.common.internal.impl.JUnitVersion;
+import org.powermock.reflect.Whitebox;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * A custom {@link MethodValidator} that makes sure that test methods not
+ * annotated by the Test annotation works in JUnit 4.4 with the custom
+ * JUnit-runner when the test class is extending {@link TestCase}. This is
+ * actually a workaround for JUnit 4.4 when the test case extends from the
+ * <code>TestCase</code> class.
+ */
+ at SuppressWarnings("deprecation")
+public class PowerMockJUnit4MethodValidator extends MethodValidator {
+
+ private static final String TEST_CLASS_FIELD;
+ private static final String CLASS_UNDER_TEST_FIELD;
+ private static final String ERRORS_FIELD;
+
+ static {
+ if(JUnitVersion.isGreaterThanOrEqualTo("4.12")) {
+ TEST_CLASS_FIELD = "testClass";
+ CLASS_UNDER_TEST_FIELD = "klass";
+ ERRORS_FIELD = "errors";
+ }
+ else {
+ TEST_CLASS_FIELD = "fTestClass";
+ CLASS_UNDER_TEST_FIELD = "fClass";
+ ERRORS_FIELD = "fErrors";
+ }
+ }
+
+ public PowerMockJUnit4MethodValidator(TestClass testClass) {
+ super(testClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void validateInstanceMethods() {
+ validateTestMethods(After.class, false);
+ validateTestMethods(Before.class, false);
+ validateTestMethods(Test.class, false);
+
+ TestClass testClass = (TestClass) Whitebox.getInternalState(this, TEST_CLASS_FIELD, MethodValidator.class);
+ Class<?> classUnderTest = (Class<?>) Whitebox.getInternalState(testClass, CLASS_UNDER_TEST_FIELD);
+ List<Throwable> fErrors = (List<Throwable>) Whitebox.getInternalState(this, ERRORS_FIELD, MethodValidator.class);
+
+ List<Method> methods = getTestMethods(testClass, classUnderTest);
+ if (methods.size() == 0)
+ fErrors.add(new Exception("No runnable methods"));
+ }
+
+ private List<Method> getTestMethods(TestClass testClass, Class<?> classUnderTest) {
+ List<Method> methods = testClass.getAnnotatedMethods(Test.class);
+ if (methods.isEmpty()) {
+ methods.addAll(getTestMethodsWithNoAnnotation(classUnderTest));
+ }
+ return methods;
+ }
+
+ /**
+ * This is a rip-off of the
+ * {@link MethodValidator#validateInstanceMethods()} with the exception that
+ * this method also searches for test methods if the class extends
+ * {@link TestCase} and has methods that starts with test which are not
+ * annotated.
+ */
+ @SuppressWarnings("unchecked")
+ private void validateTestMethods(Class<? extends Annotation> annotation, boolean isStatic) {
+ TestClass testClass = (TestClass) Whitebox.getInternalState(this, TEST_CLASS_FIELD, MethodValidator.class);
+ Class<?> classUnderTest = (Class<?>) Whitebox.getInternalState(testClass, CLASS_UNDER_TEST_FIELD);
+ final List<Method> methods;
+ if (TestCase.class.equals(classUnderTest.getSuperclass()) && !isStatic) {
+ methods = getTestMethodsWithNoAnnotation(classUnderTest);
+ } else {
+ methods = testClass.getAnnotatedMethods(annotation);
+ }
+
+ List<Throwable> fErrors = (List<Throwable>) Whitebox.getInternalState(this, ERRORS_FIELD, MethodValidator.class);
+ for (Method each : methods) {
+ if (Modifier.isStatic(each.getModifiers()) != isStatic) {
+ String state = isStatic ? "should" : "should not";
+ fErrors.add(new Exception("Method " + each.getName() + "() " + state + " be static"));
+ }
+ if (!Modifier.isPublic(each.getDeclaringClass().getModifiers()))
+ fErrors.add(new Exception("Class " + each.getDeclaringClass().getName() + " should be public"));
+ if (!Modifier.isPublic(each.getModifiers()))
+ fErrors.add(new Exception("Method " + each.getName() + " should be public"));
+ if (each.getReturnType() != Void.TYPE)
+ fErrors.add(new Exception("Method " + each.getName() + " should be void"));
+ if (each.getParameterTypes().length != 0)
+ fErrors.add(new Exception("Method " + each.getName() + " should have no parameters"));
+ }
+ }
+
+ private List<Method> getTestMethodsWithNoAnnotation(Class<?> testClass) {
+ List<Method> potentialTestMethods = new LinkedList<Method>();
+ Method[] methods = testClass.getMethods();
+ for (Method method : methods) {
+ if (method.getName().startsWith("test")) {
+ potentialTestMethods.add(method);
+ }
+ }
+ return potentialTestMethods;
+ }
+}
diff --git a/modules/module-impl/junit4/src/test/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifierTest.java b/modules/module-impl/junit4/src/test/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifierTest.java
new file mode 100644
index 0000000..bf3da75
--- /dev/null
+++ b/modules/module-impl/junit4/src/test/java/org/powermock/modules/junit4/internal/impl/PowerMockRunNotifierTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.junit4.internal.impl;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runner.notification.RunNotifier;
+import org.junit.runners.Parameterized;
+
+import static org.easymock.EasyMock.*;
+import org.junit.runner.Description;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunListener;
+import org.powermock.tests.utils.PowerMockTestNotifier;
+
+ at RunWith(Parameterized.class)
+public class PowerMockRunNotifierTest {
+
+ /*
+ * Dummy test data ...
+ */
+ private static final Object[][] testDataAlternatives;
+ static {
+ Description description =
+ Description.createSuiteDescription(Description.class);
+ testDataAlternatives = new Object[][] {
+ {description},
+ {new Failure(description, new Throwable())},
+ {new RunListener()},
+ {new Result()}
+ };
+ }
+
+ /**
+ * Parameter data
+ */
+ @Parameterized.Parameter(0) public Method method;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> runNotifierMethods() {
+ List<Object[]> methods = new ArrayList<Object[]>();
+ for (Method m : RunNotifier.class.getMethods()) {
+ if (Object.class != m.getDeclaringClass()) {
+ methods.add(new Object[] {m});
+ }
+ }
+ return methods;
+ }
+
+ @Test
+ public void verifyBackendRunNotifierIsProperlyNotified() throws Exception {
+ Object[] testData = retrieveSuitableTestData();
+ RunNotifier backendRunNotifierMock = createMock(RunNotifier.class);
+ method.invoke(backendRunNotifierMock, testData);
+ replay(backendRunNotifierMock);
+ method.invoke(new PowerMockRunNotifier(
+ backendRunNotifierMock,
+ createNiceMock(PowerMockTestNotifier.class),
+ new Method[0]),
+ testData);
+ verify(backendRunNotifierMock);
+ }
+
+ private Object[] retrieveSuitableTestData() {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ if (0 == paramTypes.length) {
+ return null;
+ }
+ for (Object[] testData : testDataAlternatives) {
+ if (paramTypes[0] == testData[0].getClass()) {
+ return testData;
+ }
+ }
+ throw new Error("No test-data available for method " + method);
+ }
+}
diff --git a/modules/module-impl/pom.xml b/modules/module-impl/pom.xml
new file mode 100644
index 0000000..e2fea62
--- /dev/null
+++ b/modules/module-impl/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-modules-impl</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ PowerMock support modules for JUnit and TestNG.
+ </description>
+
+ <modules>
+ <module>junit3</module>
+ <module>junit4</module>
+ <module>junit4-common</module>
+ <module>junit4-legacy</module>
+ <module>junit4-rule</module>
+ <module>junit4-rule-agent</module>
+ <module>testng</module>
+ <module>testng-agent</module>
+ <module>testng-common</module>
+ <module>agent</module>
+ </modules>
+</project>
diff --git a/modules/module-impl/testng-agent/pom.xml b/modules/module-impl/testng-agent/pom.xml
new file mode 100644
index 0000000..50f49c4
--- /dev/null
+++ b/modules/module-impl/testng-agent/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-testng-agent</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock module for TestNG Java agent bootstrap.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/testng-agent/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java b/modules/module-impl/testng-agent/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java
new file mode 100644
index 0000000..c3945db
--- /dev/null
+++ b/modules/module-impl/testng-agent/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng;
+
+import org.powermock.core.agent.JavaAgentClassRegister;
+import org.powermock.modules.agent.PowerMockAgent;
+import org.powermock.modules.agent.support.JavaAgentClassRegisterImpl;
+import org.powermock.modules.agent.support.PowerMockAgentTestInitializer;
+import org.testng.IObjectFactory;
+import org.testng.internal.ObjectFactoryImpl;
+
+import java.lang.reflect.Constructor;
+
+/**
+ * The PowerMock object factory for PowerMock java agent.
+ */
+public class PowerMockObjectFactory implements IObjectFactory {
+
+ static {
+ if (PowerMockObjectFactory.class.getClassLoader() != ClassLoader.getSystemClassLoader()) {
+ throw new IllegalStateException("PowerMockObjectFactory can only be used with the system classloader but was loaded by " + PowerMockObjectFactory.class.getClassLoader());
+ }
+ PowerMockAgent.initializeIfPossible();
+ }
+
+ private final ObjectFactoryImpl defaultObjectFactory;
+
+ public PowerMockObjectFactory() {
+ defaultObjectFactory = new ObjectFactoryImpl();
+ }
+
+ @Override
+ public Object newInstance(Constructor constructor, Object... params) {
+ final Class<?> testClass = constructor.getDeclaringClass();
+ JavaAgentClassRegister agentClassRegister = new JavaAgentClassRegisterImpl();
+ PowerMockAgentTestInitializer.initialize(testClass, agentClassRegister);
+ return defaultObjectFactory.newInstance(constructor, params);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-impl/testng-common/pom.xml b/modules/module-impl/testng-common/pom.xml
new file mode 100644
index 0000000..4293629
--- /dev/null
+++ b/modules/module-impl/testng-common/pom.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-testng-common</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock module for TestNG.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/testng-common/src/main/java/org/powermock/modules/testng/PowerMockTestCase.java b/modules/module-impl/testng-common/src/main/java/org/powermock/modules/testng/PowerMockTestCase.java
new file mode 100644
index 0000000..e0c4933
--- /dev/null
+++ b/modules/module-impl/testng-common/src/main/java/org/powermock/modules/testng/PowerMockTestCase.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng;
+
+import org.powermock.core.MockRepository;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.core.reporter.MockingFrameworkReporter;
+import org.powermock.core.reporter.MockingFrameworkReporterFactory;
+import org.powermock.reflect.Whitebox;
+import org.testng.IObjectFactory;
+import org.testng.ITestContext;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.ObjectFactory;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * A PowerMock base class that <i>may</i> be used as a base class for all TestNG
+ * test cases that uses PowerMock.
+ */
+public class PowerMockTestCase {
+
+ private Object annotationEnabler;
+
+ private ClassLoader previousCl = null;
+
+ private MockingFrameworkReporter frameworkReporter;
+
+ public PowerMockTestCase() {
+ try {
+ Class<?> annotationEnablerClass = Class.forName("org.powermock.api.extension.listener.AnnotationEnabler");
+ annotationEnabler = Whitebox.newInstance(annotationEnablerClass);
+ } catch (ClassNotFoundException e) {
+ annotationEnabler = null;
+ }
+ }
+
+ @BeforeClass
+ protected void beforePowerMockTestClass() throws Exception {
+ // To make sure that the mock repository is not in an incorrect state when the test begins
+ MockRepository.clear();
+ if(isLoadedByPowerMockClassloader()) {
+ final Thread thread = Thread.currentThread();
+ previousCl = thread.getContextClassLoader();
+ thread.setContextClassLoader(this.getClass().getClassLoader());
+ }
+ }
+
+ @AfterClass
+ protected void afterPowerMockTestClass() throws Exception {
+ if(previousCl != null) {
+ Thread.currentThread().setContextClassLoader(previousCl);
+ }
+ }
+
+
+ /**
+ * Must be executed before each test method. This method does the following:
+ * <ol>
+ * <li>Injects all mock fields (if they haven't been injected already)</li>
+ * </ol>
+ *
+ *
+ *
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ @BeforeMethod
+ protected void beforePowerMockTestMethod() throws Exception {
+ injectMocks();
+ enableReporter();
+ }
+
+ private void enableReporter() {
+ frameworkReporter = getFrameworkReporterFactory().create();
+ frameworkReporter.enable();
+ }
+
+ private MockingFrameworkReporterFactory getFrameworkReporterFactory() {
+ Class<MockingFrameworkReporterFactory> mockingFrameworkReporterFactoryClass;
+ try {
+ ClassLoader classLoader = this.getClass().getClassLoader();
+ mockingFrameworkReporterFactoryClass = (Class<MockingFrameworkReporterFactory>) classLoader.loadClass("org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl");
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(
+ "Extension API internal error: org.powermock.api.org.powermock.api.extension.reporter.MockingFrameworkReporterFactoryImpl could not be located in classpath.");
+ }
+
+ return Whitebox.newInstance(mockingFrameworkReporterFactoryClass);
+ }
+
+ /**
+ * Must be executed after each test method. This method does the following:
+ * <ol>
+ * <li>Clear all injection fields (those annotated with a Mock annotation)</li>
+ * <li>Clears the PowerMock MockRepository</li>
+ * </ol>
+ *
+ *
+ *
+ * @throws Exception
+ * If something unexpected goes wrong.
+ */
+ @AfterMethod
+ protected void afterPowerMockTestMethod() throws Exception {
+ try {
+ clearMockFields();
+ } finally {
+ MockRepository.clear();
+ }
+ disableReporter();
+ }
+
+ private void disableReporter() {
+ frameworkReporter.disable();
+ }
+
+ /**
+ * @return The PowerMock object factory.
+ */
+ @ObjectFactory
+ public IObjectFactory create(ITestContext context) {
+ try {
+ final Class<?> powerMockObjectFactory = Class.forName("org.powermock.modules.testng.PowerMockObjectFactory");
+ return (IObjectFactory) powerMockObjectFactory.newInstance();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Missing org.powermock.modules.testng.PowerMockObjectFactory in classpath.");
+ } catch (Exception e) {
+ throw new RuntimeException("PowerMock internal error", e);
+ }
+ }
+
+ private void clearMockFields() throws Exception, IllegalAccessException {
+ if (annotationEnabler != null) {
+ final Class<? extends Annotation>[] mockAnnotations = Whitebox.<Class<? extends Annotation>[]> invokeMethod(annotationEnabler,
+ "getMockAnnotations");
+ Set<Field> mockFields = Whitebox.getFieldsAnnotatedWith(this, mockAnnotations);
+ for (Field field : mockFields) {
+ field.set(this, null);
+ }
+ }
+ }
+
+ private void injectMocks() throws Exception {
+ if (annotationEnabler != null) {
+ Whitebox.invokeMethod(annotationEnabler, "beforeTestMethod", new Class<?>[] { Object.class, Method.class, Object[].class }, this, null,
+ null);
+ }
+ }
+
+ private boolean isLoadedByPowerMockClassloader() {
+ if(this.getClass().getClassLoader() instanceof MockClassLoader) {
+ return true;
+ }
+ return false;
+ }
+
+}
diff --git a/modules/module-impl/testng/pom.xml b/modules/module-impl/testng/pom.xml
new file mode 100644
index 0000000..50f3eea
--- /dev/null
+++ b/modules/module-impl/testng/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-module-testng</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ PowerMock module for TestNG.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java
new file mode 100644
index 0000000..b487699
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/PowerMockObjectFactory.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.testng.internal.PowerMockClassloaderObjectFactory;
+import org.testng.IObjectFactory;
+import org.testng.internal.ObjectFactoryImpl;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+/**
+ * The PowerMock object factory. If the test class or any public method declared in the test class is annotated with
+ * {@link PrepareForTest} or {@link SuppressStaticInitializationFor} the PowerMock classloader will enable the class
+ * for PowerMock testing, otherwise a standard ObjectFactory is used.
+ */
+public class PowerMockObjectFactory implements IObjectFactory {
+
+ private PowerMockClassloaderObjectFactory powerMockObjectFactory = new PowerMockClassloaderObjectFactory();
+
+ private ObjectFactoryImpl defaultObjectFactory = new ObjectFactoryImpl();
+
+ @Override
+ public Object newInstance(Constructor constructor, Object... params) {
+ final Object testInstance;
+ Class<?> testClass = constructor.getDeclaringClass();
+ if (hasPowerMockAnnotation(testClass)) {
+ testInstance = powerMockObjectFactory.newInstance(constructor, params);
+ }
+ else {
+ testInstance = defaultObjectFactory.newInstance(constructor, params);
+ }
+
+ return testInstance;
+ }
+
+ private boolean hasPowerMockAnnotation(Class<?> testClass) {
+ return isClassAnnotatedWithPowerMockAnnotation(testClass) || anyMethodInClassHasPowerMockAnnotation(testClass);
+ }
+
+ private boolean anyMethodInClassHasPowerMockAnnotation(Class<?> testClass) {
+ final Method[] methods = testClass.getMethods();
+ for (Method method : methods) {
+ if(method.isAnnotationPresent(PrepareForTest.class) || method.isAnnotationPresent(SuppressStaticInitializationFor.class)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isClassAnnotatedWithPowerMockAnnotation(Class<?> testClass) {
+ return testClass.isAnnotationPresent(PrepareForTest.class) || testClass.isAnnotationPresent(SuppressStaticInitializationFor.class);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/Assumes.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/Assumes.java
new file mode 100644
index 0000000..3f0e40c
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/Assumes.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.testng.internal;
+
+import org.testng.SkipException;
+
+/**
+ *
+ */
+public class Assumes {
+
+ public static void assumeTrue(String reason, boolean assertion) {
+ if (!assertion) {
+ throw new SkipException(reason);
+ }
+ }
+
+
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ClassLoaderFactory.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ClassLoaderFactory.java
new file mode 100644
index 0000000..a725ad2
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ClassLoaderFactory.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.testng.internal;
+
+import org.powermock.core.classloader.MockClassLoaderBuilders;
+import org.powermock.core.transformers.MockTransformer;
+import org.powermock.core.transformers.impl.ClassMockTransformer;
+import org.powermock.core.transformers.impl.InterfaceMockTransformer;
+import org.powermock.tests.utils.IgnorePackagesExtractor;
+import org.powermock.tests.utils.TestClassesExtractor;
+import org.powermock.tests.utils.impl.PowerMockIgnorePackagesExtractorImpl;
+import org.powermock.tests.utils.impl.PrepareForTestExtractorImpl;
+import org.powermock.tests.utils.impl.StaticConstructorSuppressExtractorImpl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ */
+class ClassLoaderFactory {
+
+ private final TestClassesExtractor testClassesExtractor;
+ private final IgnorePackagesExtractor ignorePackagesExtractor;
+ private final StaticConstructorSuppressExtractorImpl staticConstructorSuppressExtractor;
+ private final ExpectedExceptionsExtractor expectedExceptionsExtractor;
+ private final List<MockTransformer> mockTransformerChain;
+
+ ClassLoaderFactory() {
+
+ testClassesExtractor = new PrepareForTestExtractorImpl();
+ ignorePackagesExtractor = new PowerMockIgnorePackagesExtractorImpl();
+ expectedExceptionsExtractor = new PowerMockExpectedExceptionsExtractorImpl();
+ staticConstructorSuppressExtractor = new StaticConstructorSuppressExtractorImpl();
+
+ mockTransformerChain = getMockTransformers();
+
+ }
+
+ private List<MockTransformer> getMockTransformers() {
+ List<MockTransformer> mockTransformerChain = new ArrayList<MockTransformer>();
+
+ mockTransformerChain.add(new ClassMockTransformer());
+ mockTransformerChain.add(new InterfaceMockTransformer());
+
+ return mockTransformerChain;
+ }
+
+ ClassLoader createClassLoader(Class<?> testClass) {
+ return MockClassLoaderBuilders.mockClassLoaderBuilder()
+ .addMockTransformerChain(mockTransformerChain)
+ .addIgnorePackage(ignorePackagesExtractor.getPackagesToIgnore(testClass))
+ .addIgnorePackage(expectedExceptionsExtractor.getPackagesToIgnore(testClass))
+ .addClassesToModify(testClassesExtractor.getTestClasses(testClass))
+ .addClassesToModify(staticConstructorSuppressExtractor.getClassesToModify(testClass))
+ .build();
+ }
+
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ExpectedExceptionsExtractor.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ExpectedExceptionsExtractor.java
new file mode 100644
index 0000000..65b2f84
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/ExpectedExceptionsExtractor.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng.internal;
+
+import java.lang.reflect.AnnotatedElement;
+
+public interface ExpectedExceptionsExtractor {
+
+ /**
+ * @param element The annotated element that needs to be examined.
+ * @return Returns a string-array of all package names if annotation was found.
+ */
+ String[] getPackagesToIgnore(AnnotatedElement element);
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockClassloaderObjectFactory.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockClassloaderObjectFactory.java
new file mode 100644
index 0000000..303a8dd
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockClassloaderObjectFactory.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.powermock.modules.testng.internal;
+
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.proxyframework.ClassLoaderRegisterProxyFramework;
+import org.testng.IObjectFactory;
+
+import java.lang.reflect.Constructor;
+
+public class PowerMockClassloaderObjectFactory implements IObjectFactory {
+
+ private final ClassLoaderFactory classLoaderFactory;
+
+ public PowerMockClassloaderObjectFactory() {
+ classLoaderFactory = new ClassLoaderFactory();
+ }
+
+ @Override
+ public Object newInstance(Constructor constructor, Object... params) {
+
+ /*
+ * For extra safety clear the MockitoRepository on each new
+ * instantiation of the object factory. This is good in cases where a
+ * previous test has used e.g. PowerMock#createMock(..) to create a mock
+ * without using this factory. That means that there's some state left in
+ * the MockRepository that hasn't been cleared. Currently clearing the
+ * MockRepository from any classloader will clear the previous state but
+ * it's not certain that this is always the case.
+ */
+ MockRepository.clear();
+
+ Object testInstance = new TestClassInstanceFactory(constructor, classLoaderFactory, params).create();
+
+ ClassLoaderRegisterProxyFramework.registerProxyframework(testInstance.getClass().getClassLoader());
+
+ return testInstance;
+ }
+
+
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockExpectedExceptionsExtractorImpl.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockExpectedExceptionsExtractorImpl.java
new file mode 100644
index 0000000..f1d3d3e
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockExpectedExceptionsExtractorImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng.internal;
+
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import org.testng.annotations.Test;
+
+public class PowerMockExpectedExceptionsExtractorImpl implements ExpectedExceptionsExtractor {
+
+ public String[] getPackagesToIgnore(AnnotatedElement element) {
+ List<String> ignoredPackages = new LinkedList<String>();
+ if (element instanceof Class<?>) {
+ Class<?> klazz = (Class<?>) element;
+ for (Method method : klazz.getMethods()) {
+ Test annotation = method.getAnnotation(Test.class);
+ if (annotation != null) {
+ Class<?>[] ignores = annotation.expectedExceptions();
+ if (ignores != null) {
+ for (Class<?> ignorePackage : ignores) {
+ ignoredPackages.add(ignorePackage.getName());
+ }
+ }
+ }
+ }
+ Class<?> superclass = klazz.getSuperclass();
+ if (superclass != null && !superclass.equals(Object.class)) {
+ String[] packagesToIgnore = getPackagesToIgnore(superclass);
+ ignoredPackages.addAll(Arrays.asList(packagesToIgnore));
+ }
+ }
+
+ return ignoredPackages.toArray(new String[ignoredPackages.size()]);
+ }
+}
+
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockTestNGMethodHandler.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockTestNGMethodHandler.java
new file mode 100644
index 0000000..c1d1088
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/PowerMockTestNGMethodHandler.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng.internal;
+
+import javassist.util.proxy.MethodHandler;
+import org.powermock.core.MockRepository;
+import org.powermock.reflect.Whitebox;
+import org.testng.annotations.Test;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/*
+ * Javassist handler that takes care of cleaning up {@link MockRepository} state
+ * after each method annotated with {@link Test}.
+ */
+public class PowerMockTestNGMethodHandler implements MethodHandler {
+
+ private Object annotationEnabler;
+
+ public PowerMockTestNGMethodHandler(Class<?> testClass) {
+ try {
+ Class<?> annotationEnablerClass = Class.forName("org.powermock.api.extension.listener.AnnotationEnabler");
+ annotationEnabler = Whitebox.newInstance(annotationEnablerClass);
+ } catch (ClassNotFoundException e) {
+ annotationEnabler = null;
+ }
+ }
+
+ @Override
+ public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
+ injectMocksUsingAnnotationEnabler(self);
+ try {
+ final Object result = proceed.invoke(self, args);
+ return result;
+ } catch (InvocationTargetException e) {
+ throw e.getTargetException();
+ }
+ finally
+ {
+ if (thisMethod.isAnnotationPresent(Test.class)) {
+ clearMockFields();
+ MockRepository.clear();
+ }
+ }
+ }
+
+ private void clearMockFields() throws Exception, IllegalAccessException {
+ if (annotationEnabler != null) {
+ Set<Field> mockFields = Whitebox.getFieldsAnnotatedWith(this, Whitebox
+ .<Class<? extends Annotation>[]> invokeMethod(annotationEnabler, "getMockAnnotations"));
+ for (Field field : mockFields) {
+ field.set(this, null);
+ }
+ }
+ }
+
+ private void injectMocksUsingAnnotationEnabler(Object self) throws Exception {
+ if (annotationEnabler != null) {
+ Whitebox.invokeMethod(annotationEnabler, "beforeTestMethod", new Class<?>[] { Object.class, Method.class,
+ Object[].class }, self, null, null);
+ }
+ }
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestClassInstanceFactory.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestClassInstanceFactory.java
new file mode 100644
index 0000000..369cbba
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestClassInstanceFactory.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.modules.testng.internal;
+
+import javassist.util.proxy.ProxyFactory;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.powermock.reflect.Whitebox;
+import org.powermock.tests.utils.impl.MockPolicyInitializerImpl;
+
+import java.lang.reflect.Constructor;
+
+/**
+ *
+ */
+class TestClassInstanceFactory {
+ private final Constructor constructor;
+ private final Class<?> testClass;
+ private final Object[] params;
+ private final ClassLoader mockLoader;
+
+ TestClassInstanceFactory(Constructor constructor, ClassLoaderFactory classLoaderFactory, Object... params) {
+ this.constructor = constructor;
+ this.params = params;
+ this.testClass = constructor.getDeclaringClass();
+ this.mockLoader = classLoaderFactory.createClassLoader(testClass);
+ }
+
+ Object create() {
+
+ try {
+
+ initializeMockPolicy();
+
+ final Class<?> testClassLoadedByMockedClassLoader = createTestClass(testClass);
+ final Constructor<?> con = testClassLoadedByMockedClassLoader.getConstructor(constructor.getParameterTypes());
+ final Object testInstance = con.newInstance(params);
+
+ if (!extendsPowerMockTestCase(testClass)) {
+ setInvocationHandler(testInstance);
+ }
+
+ return testInstance;
+ } catch (Exception e) {
+ throw new RuntimeException(String.format("Cannot create a new instance of test class %s", testClass), e);
+ }
+ }
+
+ private void initializeMockPolicy() {new MockPolicyInitializerImpl(testClass).initialize(mockLoader);}
+
+
+ /**
+ * We proxy the test class in order to be able to clear state after each
+ * test method invocation. It would be much better to be able to register a
+ * testng listener programmtically but I cannot find a way to do so.
+ */
+ private Class<?> createTestClass(Class<?> actualTestClass) throws Exception {
+
+ final Class<?> testClassLoadedByMockedClassLoader = Class.forName(actualTestClass.getName(), false, mockLoader);
+
+ if (extendsPowerMockTestCase(actualTestClass)) {
+ return testClassLoadedByMockedClassLoader;
+ } else {
+ return createProxyTestClass(testClassLoadedByMockedClassLoader);
+ }
+ }
+
+ private Class<?> createProxyTestClass(Class<?> testClassLoadedByMockedClassLoader) throws Exception {
+ Class<?> proxyFactoryClass = Class.forName(ProxyFactory.class.getName(), false, mockLoader);
+ final Class<?> testNGMethodFilterByMockedClassLoader = Class.forName(TestNGMethodFilter.class.getName(), false, mockLoader);
+
+ Object f = proxyFactoryClass.newInstance();
+ Object filter = testNGMethodFilterByMockedClassLoader.newInstance();
+ Whitebox.invokeMethod(f, "setFilter", filter);
+ Whitebox.invokeMethod(f, "setSuperclass", testClassLoadedByMockedClassLoader);
+
+ return Whitebox.invokeMethod(f, "createClass");
+ }
+
+ private void setInvocationHandler(Object testInstance) throws Exception {
+ Class<?> powerMockTestNGMethodHandlerClass = Class.forName(PowerMockTestNGMethodHandler.class.getName(), false, mockLoader);
+ Object powerMockTestNGMethodHandlerInstance = powerMockTestNGMethodHandlerClass.getConstructor(Class.class)
+ .newInstance(
+ testInstance.getClass());
+ Whitebox.invokeMethod(testInstance, "setHandler", powerMockTestNGMethodHandlerInstance);
+ }
+
+ private boolean extendsPowerMockTestCase(Class<?> actualTestClass) {
+ return PowerMockTestCase.class.isAssignableFrom(actualTestClass);
+ }
+}
diff --git a/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestNGMethodFilter.java b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestNGMethodFilter.java
new file mode 100644
index 0000000..e93a94a
--- /dev/null
+++ b/modules/module-impl/testng/src/main/java/org/powermock/modules/testng/internal/TestNGMethodFilter.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.modules.testng.internal;
+
+import javassist.util.proxy.MethodFilter;
+
+import java.lang.reflect.Method;
+
+/**
+ * Javassist method filter that ignores the toString, equals, finalize and
+ * hashCode method otherwise the test output in Maven looks strange and
+ * replayAll/verifyAll doesn't work as expected.
+ */
+public class TestNGMethodFilter implements MethodFilter {
+ @Override
+ public boolean isHandled(Method method) {
+ return !isToString(method) && !isHashCode(method) && !isFinalize(method) && !isEquals(method);
+ }
+
+ private boolean isEquals(Method method) {
+ return method.getName().equals("equals") && isOneArgumentMethodOfType(method, Object.class);
+ }
+
+ private boolean isFinalize(Method method) {
+ return method.getName().equals("finalize") && isZeroArgumentMethod(method);
+ }
+
+ private boolean isHashCode(Method method) {
+ return method.getName().equals("hashCode") && isZeroArgumentMethod(method);
+ }
+
+ private boolean isToString(Method method) {
+ return (method.getName().equals("toString") && isZeroArgumentMethod(method));
+ }
+
+ private boolean isZeroArgumentMethod(Method method) {
+ return hasArgumentLength(method, 0);
+ }
+
+ private boolean hasArgumentLength(Method method, int length) {
+ return method.getParameterTypes().length == length;
+ }
+
+ private boolean isOneArgumentMethodOfType(Method method, Class<?> type) {
+ return hasArgumentLength(method, 1) && Object.class.equals(method.getParameterTypes()[0]);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/junit3-test/pom.xml b/modules/module-test/easymock/junit3-test/pom.xml
new file mode 100644
index 0000000..40e5b6e
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit3</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 3.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>3.8.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>**/StupidPrivateFinalTest.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/AllJUnit3Tests.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/AllJUnit3Tests.java
new file mode 100644
index 0000000..2f39396
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/AllJUnit3Tests.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.powermock.modules.junit3.PowerMockSuite;
+import samples.junit3.privateandfinal.PrivateFinalTest;
+import samples.junit3.privateandfinal.StupidPrivateFinalTest;
+import samples.junit3.singleton.MockStaticTest;
+import samples.junit3.suppressconstructor.SuppressConstructorHierarchyDemoTest;
+
+public class AllJUnit3Tests extends TestCase {
+
+ @SuppressWarnings("unchecked")
+ public static TestSuite suite() throws Exception {
+ return new PowerMockSuite(StupidPrivateFinalTest.class, PrivateFinalTest.class, MockStaticTest.class,
+ SuppressConstructorHierarchyDemoTest.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/AnnotationDemoWithSetupMethodTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/AnnotationDemoWithSetupMethodTest.java
new file mode 100644
index 0000000..57cf8cc
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/AnnotationDemoWithSetupMethodTest.java
@@ -0,0 +1,40 @@
+package samples.junit3.annotationbased;
+
+import junit.framework.TestCase;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly with setup methods
+ * when this is supported by junit 3.
+ */
+public class AnnotationDemoWithSetupMethodTest extends TestCase {
+
+ @org.powermock.api.easymock.annotation.Mock
+ private Service serviceMock;
+
+ private AnnotationDemo tested;
+
+ @Override
+ protected void setUp() throws Exception {
+ tested = new AnnotationDemo(serviceMock);
+ }
+
+ public void ignored_testInjectionWorked() throws Exception {
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+
+ public void testDummy() throws Exception {
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/PrivateFinalWithAnnotationTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/PrivateFinalWithAnnotationTest.java
new file mode 100644
index 0000000..0110534
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/annotationbased/PrivateFinalWithAnnotationTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3.annotationbased;
+
+import junit.framework.TestCase;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.*;
+
+/**
+ * Test class will demonstrate annotation support for JUnit 3 when this feature
+ * is available.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PrivateFinalWithAnnotationTest extends TestCase {
+
+// @SuppressWarnings("unchecked")
+// public static TestSuite suite() throws Exception {
+// return new PowerMockSuite("Unit tests for " + PrivateFinalWithAnnotationTest.class.getSimpleName(), PrivateFinalWithAnnotationTest.class);
+// }
+
+ @Mock
+ private PrivateFinal tested;
+
+ public void no_testAnnotationWorks() throws Exception {
+ final String argument = "name";
+ String expected = "Hello altered World";
+
+ expect(tested.say(argument)).andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say(argument);
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ public void testDummy() throws Exception {
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/PrivateFinalTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/PrivateFinalTest.java
new file mode 100644
index 0000000..43c173c
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/PrivateFinalTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3.privateandfinal;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit3.PowerMockSuite;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PrivateFinalTest extends TestCase {
+
+ @SuppressWarnings("unchecked")
+ public static TestSuite suite() throws Exception {
+ return new PowerMockSuite("Unit tests for " + PrivateFinalTest.class.getSimpleName(), PrivateFinalTest.class);
+ }
+
+ public void testSay() throws Exception {
+ PrivateFinal tested = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ public void testMultiMock() throws Exception {
+ PrivateFinal tested1 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected1 = "Hello altered World";
+ expectPrivate(tested1, "sayIt", "name").andReturn(expected1);
+ replay(tested1);
+ PrivateFinal tested2 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected2 = "Hello qweqweqwe";
+ expectPrivate(tested2, "sayIt", "name").andReturn(expected2);
+ replay(tested2);
+
+ String actual1 = tested1.say("name");
+ verify(tested1);
+ assertEquals("Expected and actual did not match", expected1, actual1);
+ String actual2 = tested2.say("name");
+ verify(tested2);
+ assertEquals("Expected and actual did not match", expected2, actual2);
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/StupidPrivateFinalTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/StupidPrivateFinalTest.java
new file mode 100644
index 0000000..39d071d
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/privateandfinal/StupidPrivateFinalTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3.privateandfinal;
+
+import junit.framework.TestCase;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking. No suite is added in
+ * this class to demonstrate that you can run the test from an external test
+ * suite.
+ *
+ * @author Johan Haleby
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class StupidPrivateFinalTest extends TestCase {
+
+ public void testSay() throws Exception {
+
+ PrivateFinal tested = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ public void testMultiMock() throws Exception {
+ PrivateFinal tested1 = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected1 = "Hello altered World";
+ expectPrivate(tested1, "sayIt", "name").andReturn(expected1);
+ replay(tested1);
+ PrivateFinal tested2 = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected2 = "Hello qweqweqwe";
+ expectPrivate(tested2, "sayIt", "name").andReturn(expected2);
+ replay(tested2);
+
+ String actual1 = tested1.say("name");
+ verify(tested1);
+ assertEquals("Expected and actual did not match", expected1, actual1);
+ String actual2 = tested2.say("name");
+ verify(tested2);
+ assertEquals("Expected and actual did not match", expected2, actual2);
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/singleton/MockStaticTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/singleton/MockStaticTest.java
new file mode 100644
index 0000000..ced4760
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/singleton/MockStaticTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3.singleton;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit3.PowerMockSuite;
+import org.powermock.reflect.Whitebox;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest extends TestCase {
+
+ public static TestSuite suite() throws Exception {
+ // This is not the best way to add a test suite, but we do this here
+ // for testing purposes.
+ PowerMockSuite powerMockJunit3Suite = new PowerMockSuite("Unit tests for " + MockStaticTest.class.getSimpleName());
+ final MockStaticTest stupidSingletonTest = new MockStaticTest();
+ stupidSingletonTest.setName("testSay");
+ TestSuite suite = new TestSuite();
+ suite.addTest(stupidSingletonTest);
+ powerMockJunit3Suite.addTest(suite);
+ return powerMockJunit3Suite;
+ }
+
+ public void testSay() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ public void testSayFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.sayFinal("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.sayFinal(\"world\"):", e.getMessage());
+ }
+ }
+
+ public void testSayNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ public void testSayFinalNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinalNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ public void testMockAStaticMethod() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "qwe";
+ expect(StaticService.doStatic(5)).andReturn(expected);
+ replay(StaticService.class);
+
+ String actual = StaticService.doStatic(5);
+ assertEquals(expected, actual);
+ verify(StaticService.class);
+ }
+
+ public void testMockSayHello() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloHelper();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHello();
+
+ verify(StaticHelper.class);
+ }
+
+ public void testMockSayHelloAgain() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloAgain();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHelloAgain();
+
+ verify(StaticHelper.class);
+ }
+
+ public void testSayPrivateStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ public void testSayPrivateFinalStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateFinalStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateFinalStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateFinalStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ public void testInnerClassesWork() throws Exception {
+ assertEquals(17, StaticService.getNumberFromInner());
+ }
+
+ public void testInnerInstanceClassesWork() throws Exception {
+ assertEquals(23, StaticService.getNumberFromInnerInstance());
+ }
+}
diff --git a/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/suppressconstructor/SuppressConstructorHierarchyDemoTest.java b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
new file mode 100644
index 0000000..28d0790
--- /dev/null
+++ b/modules/module-test/easymock/junit3-test/src/test/java/samples/junit3/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit3.suppressconstructor;
+
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit3.PowerMockSuite;
+import samples.suppressconstructor.SuppressConstructorHeirarchyEvilGrandParent;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+import samples.suppressconstructor.SuppressConstructorHierarchyParent;
+
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at PrepareForTest( { SuppressConstructorHierarchy.class, SuppressConstructorHierarchyParent.class,
+ SuppressConstructorHeirarchyEvilGrandParent.class })
+public class SuppressConstructorHierarchyDemoTest extends TestCase {
+
+ @SuppressWarnings("unchecked")
+ public static TestSuite suite() throws Exception {
+ return new PowerMockSuite(SuppressConstructorHierarchyDemoTest.class);
+ }
+
+ public void testSuppressConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+
+ final String message = tested.getMessage();
+ assertNull("Message should have been null since we're skipping the execution of the constructor code. Message was \"" + message + "\".",
+ message);
+ }
+
+ @PrepareForTest
+ public void testNotSuppressConstructor() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ /**
+ * This simple test demonstrate that it's possible to continue execution
+ * with the default <code>PrepareForTest</code> settings (i.e. using a
+ * byte-code manipulated version of the SuppressConstructorHierarchyDemo
+ * class).
+ */
+ public void testGetNumber() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+ assertEquals(42, tested.getNumber());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-agent/pom.xml b/modules/module-test/easymock/junit4-agent/pom.xml
new file mode 100644
index 0000000..cdf5902
--- /dev/null
+++ b/modules/module-test/easymock/junit4-agent/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit4-agent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for PowerMock Java agent with JUnit4 and Easymock
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>
+ -javaagent:${settings.localRepository}//org/powermock/powermock-module-javaagent/${project.version}/powermock-module-javaagent-${project.version}.jar
+ </argLine>
+ <useSystemClassloader>true</useSystemClassloader>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java b/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java
new file mode 100644
index 0000000..bdd82d6
--- /dev/null
+++ b/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.agent;
+
+import org.easymock.Mock;
+import org.easymock.TestSubject;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import java.util.Arrays;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replay;
+
+ at RunWith(Parameterized.class)
+public class AnnotationUsageTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+
+ @TestSubject
+ private final
+ AnnotationDemo tested = new AnnotationDemo();
+
+
+ @SuppressWarnings("unused")
+ @Mock
+ private Service server;
+
+ private final String fooId;
+
+
+ public AnnotationUsageTest(String fooId) {
+ this.fooId = fooId;
+ }
+
+
+ @Parameterized.Parameters()
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {"1"},
+ {"2"}
+ });
+ }
+
+
+ @Before
+ public void setUp() {
+ expect(server.getServiceMessage()).andReturn(fooId);
+ replay(server);
+ }
+
+
+ @Test
+ public void annotationsAreEnabledWhenUsingTheJUnitRule() {
+ String serviceMessage = tested.getServiceMessage();
+ assertEquals(fooId, serviceMessage);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java b/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java
new file mode 100644
index 0000000..49d336c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java
@@ -0,0 +1,58 @@
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.largemethod.MethodExceedingJvmLimit;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.method;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.suppress;
+
+ at PrepareForTest(MethodExceedingJvmLimit.class)
+public class LargeMethodTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void largeMethodShouldBeOverridden() {
+ try {
+ MethodExceedingJvmLimit.init();
+ fail("Method should be overridden and exception should be thrown");
+ } catch (Exception e) {
+ assertSame(IllegalAccessException.class, e.getClass());
+ assertTrue(e.getMessage().contains("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeSuppressed() {
+ suppress(method(MethodExceedingJvmLimit.class, "init"));
+ assertNull("Suppressed method should return: null", MethodExceedingJvmLimit.init());
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeMocked() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ expect(MethodExceedingJvmLimit.init()).andReturn("ok");
+ replayAll();
+ assertEquals("Mocked method should return: ok", "ok", MethodExceedingJvmLimit.init());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void largeMethodShouldBeAbleToBeMockedAndThrowException() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ expect(MethodExceedingJvmLimit.init()).andThrow(new IllegalStateException());
+ replayAll();
+ MethodExceedingJvmLimit.init();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/pom.xml b/modules/module-test/easymock/junit4-legacy-test/pom.xml
new file mode 100644
index 0000000..763ea69
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit4-legacy</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.0-4.3.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.3</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/AllJUnit4LegacyTests.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/AllJUnit4LegacyTests.java
new file mode 100644
index 0000000..f77069a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/AllJUnit4LegacyTests.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.legacy;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import samples.junit4.legacy.noannotation.NoAnnotationUsageTest;
+import samples.junit4.legacy.singleton.MockStaticTest;
+import samples.junit4.legacy.suppressconstructor.SuppressConstructorHierarchyDemoTest;
+
+ at RunWith(Suite.class)
+ at SuiteClasses( { MockStaticTest.class, SuppressConstructorHierarchyDemoTest.class, NoAnnotationUsageTest.class })
+public class AllJUnit4LegacyTests {
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/AnnotationDemoWithSetupMethodTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/AnnotationDemoWithSetupMethodTest.java
new file mode 100644
index 0000000..d688b02
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/AnnotationDemoWithSetupMethodTest.java
@@ -0,0 +1,43 @@
+package samples.junit4.legacy.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly with setup methods.
+ */
+ at RunWith(PowerMockRunner.class)
+public class AnnotationDemoWithSetupMethodTest {
+
+ @Mock
+ private Service serviceMock;
+
+ private AnnotationDemo tested;
+
+ @Before
+ public void setup() {
+ tested = new AnnotationDemo(serviceMock);
+ }
+
+ @Test
+ public void assertInjectionWorked() throws Exception {
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/FinalDemoWithAnnotationInjectionTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/FinalDemoWithAnnotationInjectionTest.java
new file mode 100644
index 0000000..981186b
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/annotationbased/FinalDemoWithAnnotationInjectionTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.legacy.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoWithAnnotationInjectionTest {
+
+ @Mock
+ private FinalDemo tested;
+
+ @Test
+ public void testSay() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/NoAnnotationUsageTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/NoAnnotationUsageTest.java
new file mode 100644
index 0000000..3d52a68
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/NoAnnotationUsageTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.legacy.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test case that demonstrates the ability to run test cases not annotated with
+ * {@link Test} when extending from {@link TestCase} using JUnit4 legacy
+ * (4.0-4.3).
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class NoAnnotationUsageTest extends TestCase {
+
+ public void testGetMessage() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class, "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+
+ public void testGetMessage2() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class, "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java
new file mode 100644
index 0000000..cdca995
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java
@@ -0,0 +1,30 @@
+package samples.junit4.legacy.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+
+ at RunWith(PowerMockRunner.class)
+public class SetUpAndTearDownWhenExtendingTestCaseTest extends TestCase {
+ private static final String INITIAL_MESSAGE = "";
+ private static final String SET_UP_MESSAGE = "setUp";
+ private static final String TEST_MESSAGE = "test";
+
+ private static String CURRENT_MESSAGE = INITIAL_MESSAGE;
+
+ @Override
+ protected void setUp() throws Exception {
+ assertEquals(INITIAL_MESSAGE, CURRENT_MESSAGE);
+ CURRENT_MESSAGE = SET_UP_MESSAGE;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ assertEquals(TEST_MESSAGE, CURRENT_MESSAGE);
+ }
+
+ public void testSomething() throws Exception {
+ assertEquals(SET_UP_MESSAGE, CURRENT_MESSAGE);
+ CURRENT_MESSAGE = TEST_MESSAGE;
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java
new file mode 100644
index 0000000..46899fa
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java
@@ -0,0 +1,27 @@
+package samples.junit4.legacy.noannotation;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+ at RunWith(PowerMockRunner.class)
+public class SetUpAndTearDownWhenNotExtendingTestCaseTest {
+ private static final String INITIAL_MESSAGE = "";
+ private static String CURRENT_MESSAGE = INITIAL_MESSAGE;
+
+ public void setUp() throws Exception {
+ fail("Should not call setUp");
+ }
+
+ public void tearDown() throws Exception {
+ fail("Should not call tearDown");
+ }
+
+ @Test
+ public void testSomething() throws Exception {
+ assertEquals(INITIAL_MESSAGE, CURRENT_MESSAGE);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/singleton/MockStaticTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/singleton/MockStaticTest.java
new file mode 100644
index 0000000..b590edc
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/singleton/MockStaticTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.legacy.singleton;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+
+ @Test
+ public void testSay() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSayFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.sayFinal("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.sayFinal(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSayNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void sayFinalNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinalNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void mockAStaticMethod() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "qwe";
+ expect(StaticService.doStatic(5)).andReturn(expected);
+ replay(StaticService.class);
+
+ String actual = StaticService.doStatic(5);
+ assertEquals(expected, actual);
+ verify(StaticService.class);
+ }
+
+ @Test
+ public void mockSayHello() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloHelper();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHello();
+
+ verify(StaticHelper.class);
+ }
+
+ @Test
+ public void mockSayHelloAgain() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloAgain();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHelloAgain();
+
+ verify(StaticHelper.class);
+ }
+
+ @Test
+ public void testSayPrivateStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSayPrivateFinalStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateFinalStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateFinalStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateFinalStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void innerClassesWork() {
+ assertThat(StaticService.getNumberFromInner()).isEqualTo(17);
+ }
+
+ @Test
+ public void innerInstanceClassesWork() {
+ assertThat(StaticService.getNumberFromInnerInstance()).isEqualTo(23);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/suppressconstructor/SuppressConstructorHierarchyDemoTest.java b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
new file mode 100644
index 0000000..cb8c9c4
--- /dev/null
+++ b/modules/module-test/easymock/junit4-legacy-test/src/test/java/samples/junit4/legacy/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.legacy.suppressconstructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.legacy.PowerMockRunner;
+import samples.suppressconstructor.SuppressConstructorHeirarchyEvilGrandParent;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+import samples.suppressconstructor.SuppressConstructorHierarchyParent;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at PrepareForTest( { SuppressConstructorHierarchy.class, SuppressConstructorHierarchyParent.class,
+ SuppressConstructorHeirarchyEvilGrandParent.class })
+ at RunWith(PowerMockRunner.class)
+public class SuppressConstructorHierarchyDemoTest {
+
+ @Test
+ public void testSuppressConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+
+ final String message = tested.getMessage();
+ assertNull("Message should have been null since we're skipping the execution of the constructor code. Message was \"" + message + "\".",
+ message);
+ }
+
+ @Test
+ @PrepareForTest
+ public void testNotSuppressConstructor() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ /**
+ * This simple test demonstrate that it's possible to continue execution
+ * with the default <code>PrepareForTest</code> settings (i.e. using a
+ * byte-code manipulated version of the SuppressConstructorHierarchyDemo
+ * class).
+ */
+ @Test
+ public void testGetNumber() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+ assertThat(tested.getNumber()).isEqualTo(42);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/pom.xml b/modules/module-test/easymock/junit4-test/pom.xml
new file mode 100644
index 0000000..ee85530
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit4</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>junit</artifactId>
+ <groupId>junit</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <artifactId>junit</artifactId>
+ <groupId>junit</groupId>
+ <version>4.4</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsageTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsageTest.java
new file mode 100644
index 0000000..0ec3425
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsageTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.interfacemethodfinding;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+/**
+ * There was a bug in PowerMock 1.2 and its predecessors that made PowerMock
+ * {@link WhiteboxImpl#getMethod(Class, Class...)} fail when invoking proxified
+ * interface methods declared in extended interfaces. E.g. if interface A
+ * extends B & C and a method was declared in B it wouldn't be found by
+ * {@link WhiteboxImpl#getMethod(Class, Class...)} since it only used to
+ * traverse the class hierarchy and not the structure of the extended
+ * interfaces. This was fixed in version 1.3 and this test demonstrates that
+ * it's solved.
+ * <p>
+ * Thanks to Lokesh Vaddi for finding this bug and to provide an example.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { InterfaceMethodHierarchyUsage.class, WsUtil.class })
+public class InterfaceMethodHierarchyUsageTest {
+
+ private InterfaceMethodHierarchyUsage myClass;
+
+ @Test
+ public void assertMethodsAreFoundInInterfaceHierarchy() throws Exception {
+ Connection mockConnection = PowerMock.createMock(Connection.class);
+ PowerMock.mockStaticPartial(WsUtil.class, "getConnection");
+ PreparedStatement mockPrepared = PowerMock.createMock(PreparedStatement.class);
+ EasyMock.expect(WsUtil.getConnection()).andReturn(mockConnection);
+ EasyMock.expect(mockConnection.prepareStatement("select * from emp")).andReturn(mockPrepared);
+ mockConnection.close();
+ EasyMock.expectLastCall();
+ mockPrepared.close();
+ EasyMock.expectLastCall();
+
+ PowerMock.replayAll();
+ myClass = new InterfaceMethodHierarchyUsage();
+ myClass.usePreparedStatement();
+ PowerMock.verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/AllJUnit4Tests.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/AllJUnit4Tests.java
new file mode 100644
index 0000000..571b823
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/AllJUnit4Tests.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import samples.junit4.constructor.PrivateConstructorInstantiationDemoTest;
+import samples.junit4.constructorargs.ConstructorArgsDemoTest;
+import samples.junit4.expectnew.ExpectNewDemoTest;
+import samples.junit4.expectvoid.ExpectVoidDemoTest;
+import samples.junit4.finalmocking.FinalDemoTest;
+import samples.junit4.newmocking.StupidNewTest;
+import samples.junit4.noannotation.NoAnnotationUsageTest;
+import samples.junit4.partialmocking.MockSelfDemoTest;
+import samples.junit4.partialmocking.MockSelfDemoWithSubClassTest;
+import samples.junit4.privateandfinal.PrivateFinalTest;
+import samples.junit4.privatefield.MockSelfPrivateFieldServiceClassTest;
+import samples.junit4.privatefield.SimplePrivateFieldServiceClassTest;
+import samples.junit4.privatemocking.PrivateMethodDemoTest;
+import samples.junit4.simplereturn.SimpleReturnExampleUserTest;
+import samples.junit4.singleton.MockStaticTest;
+import samples.junit4.staticandinstance.StaticAndInstanceDemoTest;
+import samples.junit4.staticinitializer.StaticInitializerExampleTest;
+import samples.junit4.suppressconstructor.SuppressConstructorDemoTest;
+import samples.junit4.suppressconstructor.SuppressConstructorHierarchyDemoTest;
+import samples.junit4.suppressmethod.SuppressMethodTest;
+import samples.suppressconstructor.SuppressSpecificConstructorDemoTest;
+
+ at RunWith(Suite.class)
+ at SuiteClasses( { PrivateConstructorInstantiationDemoTest.class, ExpectNewDemoTest.class,
+ ExpectVoidDemoTest.class, FinalDemoTest.class, MockSelfDemoTest.class, MockSelfDemoWithSubClassTest.class, StupidNewTest.class,
+ PrivateFinalTest.class, MockSelfPrivateFieldServiceClassTest.class, SimplePrivateFieldServiceClassTest.class,
+ PrivateMethodDemoTest.class, MockStaticTest.class, StaticAndInstanceDemoTest.class, SuppressMethodTest.class,
+ SuppressConstructorDemoTest.class, SuppressConstructorHierarchyDemoTest.class, SuppressSpecificConstructorDemoTest.class,
+ ConstructorArgsDemoTest.class, NoAnnotationUsageTest.class, SimpleReturnExampleUserTest.class, StaticInitializerExampleTest.class })
+public class AllJUnit4Tests {
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/SomeJUnit4Tests.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/SomeJUnit4Tests.java
new file mode 100644
index 0000000..d5222a2
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/SomeJUnit4Tests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import samples.junit4.constructorargs.ConstructorArgsDemoTest;
+import samples.junit4.expectvoid.ExpectVoidDemoTest;
+import samples.junit4.finalmocking.FinalDemoTest;
+import samples.junit4.newmocking.StupidNewTest;
+import samples.junit4.noannotation.NoAnnotationUsageTest;
+import samples.junit4.partialmocking.MockSelfDemoTest;
+import samples.junit4.partialmocking.MockSelfDemoWithSubClassTest;
+import samples.junit4.prepareeverything.ExpectNewDemoUsingThePrepareEverythingAnnotationTest;
+import samples.junit4.privateandfinal.PrivateFinalTest;
+import samples.junit4.privatefield.MockSelfPrivateFieldServiceClassTest;
+import samples.junit4.privatefield.SimplePrivateFieldServiceClassTest;
+import samples.junit4.privatemocking.PrivateMethodDemoTest;
+import samples.junit4.simplereturn.SimpleReturnExampleUserTest;
+import samples.junit4.singleton.MockStaticTest;
+import samples.junit4.staticandinstance.StaticAndInstanceDemoTest;
+import samples.junit4.staticinitializer.StaticInitializerExampleTest;
+import samples.junit4.suppressconstructor.SuppressConstructorDemoTest;
+import samples.junit4.suppressconstructor.SuppressConstructorHierarchyDemoTest;
+import samples.junit4.suppressmethod.SuppressMethodTest;
+import samples.suppressconstructor.SuppressSpecificConstructorDemoTest;
+
+// This test verifies that the SuppressConstructorHierachyDemo works, issue http://code.google.com/p/powermock/issues/detail?id=43.
+
+ at RunWith(Suite.class)
+ at SuiteClasses( { ExpectVoidDemoTest.class, FinalDemoTest.class, MockSelfDemoTest.class, MockSelfDemoWithSubClassTest.class, StupidNewTest.class,
+ PrivateFinalTest.class, MockSelfPrivateFieldServiceClassTest.class, SimplePrivateFieldServiceClassTest.class, PrivateMethodDemoTest.class,
+ MockStaticTest.class, StaticAndInstanceDemoTest.class, SuppressMethodTest.class, SuppressConstructorDemoTest.class,
+ SuppressConstructorHierarchyDemoTest.class, SuppressSpecificConstructorDemoTest.class, ConstructorArgsDemoTest.class,
+ NoAnnotationUsageTest.class, SimpleReturnExampleUserTest.class, StaticInitializerExampleTest.class,
+ ExpectNewDemoUsingThePrepareEverythingAnnotationTest.class })
+public class SomeJUnit4Tests {
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/abstractmocking/AbstractMethodMockingTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/abstractmocking/AbstractMethodMockingTest.java
new file mode 100644
index 0000000..4d9ccc8
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/abstractmocking/AbstractMethodMockingTest.java
@@ -0,0 +1,30 @@
+package samples.junit4.abstractmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.abstractmocking.AbstractMethodMocking;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(AbstractMethodMocking.class)
+public class AbstractMethodMockingTest {
+
+ @Test
+ public void testMockingOfAbstractMethod() throws Exception {
+ final String value = "a string";
+ AbstractMethodMocking tested = createPartialMock(
+ AbstractMethodMocking.class, "getIt");
+
+ expectPrivate(tested, "getIt").andReturn(value);
+
+ replay(tested);
+
+ assertEquals(value, tested.getValue());
+
+ verify(tested);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/AnnotationDemoWithSetupMethodTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/AnnotationDemoWithSetupMethodTest.java
new file mode 100644
index 0000000..12510ce
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/AnnotationDemoWithSetupMethodTest.java
@@ -0,0 +1,42 @@
+package samples.junit4.annotationbased;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly with setup methods.
+ */
+ at RunWith(PowerMockRunner.class)
+public class AnnotationDemoWithSetupMethodTest {
+
+ @org.powermock.api.easymock.annotation.Mock
+ private Service serviceMock;
+
+ private AnnotationDemo tested;
+
+ @Before
+ public void setup() {
+ tested = new AnnotationDemo(serviceMock);
+ }
+
+ @Test
+ public void assertInjectionWorked() throws Exception {
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java
new file mode 100644
index 0000000..3ef581d
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PowerMockListener;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.testlisteners.FieldDefaulter;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with multiple test
+ * listeners.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+ at PowerMockListener( { FieldDefaulter.class })
+public class FinalDemoWithAnnotationInjectionAndFieldDefaulterTest {
+
+ @SuppressWarnings("unused")
+ // Asserts that the FieldDefaulter handles primitive types.
+ private int intType = 6;
+
+ @Mock
+ private FinalDemo tested;
+
+ @Test
+ public void testSay() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionTest.java
new file mode 100644
index 0000000..bbbfeeb
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionTest.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with one listeners.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoWithAnnotationInjectionTest {
+
+ @Mock
+ private FinalDemo tested;
+
+ @Test
+ public void testSay() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should no longer be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithNiceAnnotationInjectionTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithNiceAnnotationInjectionTest.java
new file mode 100644
index 0000000..b1e931b
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithNiceAnnotationInjectionTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with one listeners
+ * injecting mocks to fields annotated with {@link MockNice}.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoWithNiceAnnotationInjectionTest {
+
+ @MockNice
+ private FinalDemo tested;
+
+ @Test
+ public void testSay() throws Exception {
+ String expected = null;
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ String actual2 = tested.say("world");
+ assertEquals(expected, actual2);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithStrictAnnotationInjectionTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithStrictAnnotationInjectionTest.java
new file mode 100644
index 0000000..b3ee32d
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithStrictAnnotationInjectionTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.MockNice;
+import org.powermock.api.easymock.annotation.MockStrict;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with one listeners
+ * injecting mocks to fields annotated with {@link MockNice}.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoWithStrictAnnotationInjectionTest {
+
+ @MockStrict
+ private FinalDemo tested;
+
+ @Test
+ public void testMockStrictOk() throws Exception {
+ String expected = "Hello altered World";
+
+ expect(tested.say("hello")).andReturn(expected);
+ expect(tested.say("hello2")).andReturn(expected);
+
+ replay(tested);
+
+ String actual = tested.say("hello");
+ String actual2 = tested.say("hello2");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ assertEquals("Expected and actual did not match", expected, actual2);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testMockStrictNotOk() throws Exception {
+ String expected = "Hello altered World";
+
+ expect(tested.say("hello")).andReturn(expected);
+
+ replay(tested);
+
+ tested.say("hello2");
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectEasymockAnnotationTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectEasymockAnnotationTest.java
new file mode 100644
index 0000000..04ccb7c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectEasymockAnnotationTest.java
@@ -0,0 +1,44 @@
+package samples.junit4.annotationbased;
+
+import org.easymock.Mock;
+import org.easymock.TestSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.injectmocks.InjectDemo;
+import samples.injectmocks.InjectDependencyHolder;
+import samples.injectmocks.InjectDependencyHolderQualifier;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Asserts that {@link @TestSubject} with PowerMock and mock witch created via @org.easymock.Mock.
+ */
+ at RunWith(PowerMockRunner.class)
+public class TestSubjectEasymockAnnotationTest {
+
+ @SuppressWarnings("unused")
+ @Mock
+ private InjectDemo injectDemoEasymock;
+
+ @TestSubject
+ private final InjectDependencyHolder dependencyHolder = new InjectDependencyHolder();
+
+ @SuppressWarnings("unused")
+ @Mock(fieldName = "injectDemoQualifier")
+ private InjectDemo injectDemoQualifierEasymock;
+
+ @TestSubject
+ private final InjectDependencyHolderQualifier dependencyHolderQualifier = new InjectDependencyHolderQualifier();
+
+ @Test
+ public void injectMocksWorksWithEasymock() {
+ assertNotNull("dependencyHolder is null", dependencyHolder.getInjectDemo());
+ }
+
+ @Test
+ public void injectMocksWorksWithEasymockQualifier() {
+ assertNotNull("dependencyHolder is null", dependencyHolderQualifier.getInjectDemoQualifier());
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectPowermockAnnotationTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectPowermockAnnotationTest.java
new file mode 100644
index 0000000..fc48019
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/annotationbased/TestSubjectPowermockAnnotationTest.java
@@ -0,0 +1,80 @@
+package samples.junit4.annotationbased;
+
+import org.easymock.TestSubject;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.injectmocks.InjectDemo;
+import samples.injectmocks.InjectDependencyHolder;
+import samples.injectmocks.InjectDependencyHolderQualifier;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+import static org.powermock.api.easymock.PowerMock.replay;
+
+/**
+ * Asserts that {@link @TestSubject} with PowerMock and mock witch created via @org.powermock.api.easymock.annotation.Mock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(InjectDemo.class)
+public class TestSubjectPowermockAnnotationTest {
+
+ @SuppressWarnings("unused")
+ @Mock
+ private InjectDemo injectDemoEasymock;
+
+ @TestSubject
+ private final InjectDependencyHolder dependencyHolder = new InjectDependencyHolder();
+
+ @SuppressWarnings("unused")
+ @Mock(fieldName = "injectDemoQualifier")
+ private InjectDemo injectDemoQualifierEasymock;
+
+ @TestSubject
+ private final InjectDependencyHolderQualifier dependencyHolderQualifier = new InjectDependencyHolderQualifier();
+
+
+ @Test
+ public void injectMocksWorksWithPowermockMock() {
+ assertNotNull("dependencyHolder is null", dependencyHolder.getInjectDemo());
+ }
+
+ @Test
+ public void testInjectDemoSay() throws Exception {
+
+ InjectDemo tested = dependencyHolder.getInjectDemo();
+
+ String expected = "Hello altered World";
+ expectPrivate(tested,"say","hello").andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = Whitebox.invokeMethod(tested,"say", "hello");
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void injectMocksWorksWithPowermockMockWithQualifier() {
+ assertNotNull("dependencyHolder is null", dependencyHolderQualifier.getInjectDemoQualifier());
+ }
+
+ @Test
+ public void testInjectDemoQualifier() throws Exception {
+
+ InjectDemo tested = dependencyHolderQualifier.getInjectDemoQualifier();
+
+ String expected = "Hello altered World";
+ expectPrivate(tested,"say","hello").andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = Whitebox.invokeMethod(tested,"say", "hello");
+
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/assume/AssumeTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/assume/AssumeTest.java
new file mode 100644
index 0000000..9a1d4e5
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/assume/AssumeTest.java
@@ -0,0 +1,18 @@
+package samples.junit4.assume;
+
+import org.junit.Assume;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assume.assumeTrue;
+
+ at RunWith(PowerMockRunner.class)
+public class AssumeTest {
+
+ @Test
+ public void assumesWorkWithPowerMockForJUnit44() throws Exception {
+ // When
+ assumeTrue(false);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classhierarchy/CommonParentTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classhierarchy/CommonParentTest.java
new file mode 100644
index 0000000..8a8b7ad
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classhierarchy/CommonParentTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.classhierarchy;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.ChildB;
+import samples.classhierarchy.Parent;
+
+import static org.junit.Assert.assertEquals;
+
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({ChildA.class, ChildB.class, Parent.class})
+public class CommonParentTest {
+
+ @Test
+ public void testPossibleToMockTwoClassesWithSameParent() throws Exception {
+ ChildA a = PowerMock.createMock(ChildA.class);
+ EasyMock.expect(a.getValue()).andReturn(5);
+
+ PowerMock.replay(a);
+
+ assertEquals(5, a.getValue());
+
+ PowerMock.verify(a);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classwithinnermembers/ClassWithInnerMembersTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classwithinnermembers/ClassWithInnerMembersTest.java
new file mode 100644
index 0000000..ee3cf76
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/classwithinnermembers/ClassWithInnerMembersTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.classwithinnermembers;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.classwithinnermembers.ClassWithInnerMembers;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test PowerMock's basic support for inner (member) and local classes.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ClassWithInnerMembers.class)
+public class ClassWithInnerMembersTest {
+
+ @Test
+ public void assertStaticMemberClassMockingWorksWithNoConstructorArguments() throws Exception {
+ Class<Object> innerClassType = Whitebox.getInnerClassType(ClassWithInnerMembers.class, "MyInnerClass");
+ Object innerClassMock = createMock(innerClassType);
+ expectNew(innerClassType).andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getValue());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertStaticMemberClassMockingWorksWithConstructorArguments() throws Exception {
+ Class<Object> innerClassType = Whitebox.getInnerClassType(ClassWithInnerMembers.class, "StaticInnerClassWithConstructorArgument");
+ Object innerClassMock = createMock(innerClassType);
+ expectNew(innerClassType, "value").andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getValueForStaticInnerClassWithConstructorArgument());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertLocalClassMockingWorks() throws Exception {
+
+ final Class<Object> type = Whitebox.getLocalClassType(ClassWithInnerMembers.class, 1, "MyLocalClass");
+ Object innerClassMock = createMock(type);
+ expectNew(type).andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getLocalClassValue());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertLocalClassMockingWorksWithArguments() throws Exception {
+ final Class<Object> type = Whitebox.getLocalClassType(ClassWithInnerMembers.class, 2, "MyLocalClass");
+ Object innerClassMock = createMock(type);
+ expectNew(type, "my value").andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getLocalClassValueWithArgument());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertNonStaticMemberClassMockingWorksWithArguments() throws Exception {
+ Class<Object> innerClassType = Whitebox.getInnerClassType(ClassWithInnerMembers.class, "MyInnerClassWithConstructorArgument");
+ Object innerClassMock = createMock(innerClassType);
+ expectNew(innerClassType, "value").andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getValueForInnerClassWithConstructorArgument());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatAnonymousInnerClassesWorks() throws Exception {
+ final Class<Object> type = Whitebox.getAnonymousInnerClassType(ClassWithInnerMembers.class, 1);
+ Object innerClassMock = createMock(type);
+ expectNew(type).andReturn(innerClassMock);
+ expectPrivate(innerClassMock, "doStuff").andReturn("something else");
+
+ replayAll();
+
+ assertEquals("something else", new ClassWithInnerMembers().getValueForAnonymousInnerClass());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/console/ConsoleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/console/ConsoleTest.java
new file mode 100644
index 0000000..b58f122
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/console/ConsoleTest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.console;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.io.Console;
+
+import static org.powermock.api.easymock.PowerMock.createMock;
+
+/**
+ * Asserts that PowerMock can mock the Console class. This failed in version 1.4
+ * when the DefaultFieldValueGenerator was introduced. This tests makes sure
+ * that the DefaultFieldValueGenerator can generate default values for field
+ * that are interfaces and abstract with no inheritable constructor.
+ */
+ at RunWith(PowerMockRunner.class)
+public class ConsoleTest {
+
+ @Test
+ public void canMockConsole() throws Exception {
+ createMock(Console.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PrivateConstructorInstantiationDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PrivateConstructorInstantiationDemoTest.java
new file mode 100644
index 0000000..39320bb
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PrivateConstructorInstantiationDemoTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.constructor;
+
+import org.junit.Test;
+import samples.constructor.PrivateConstructorInstantiationDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.reflect.Whitebox.invokeConstructor;
+
+
+public class PrivateConstructorInstantiationDemoTest {
+
+ @Test
+ public void testGetState_noArgConstructor() throws Exception {
+ final int expected = 42;
+ PrivateConstructorInstantiationDemo tested = invokeConstructor(PrivateConstructorInstantiationDemo.class);
+ int actual = tested.getState();
+
+ assertEquals("Expected and actual did not match.", expected, actual);
+ }
+
+ @Test
+ public void testGetState_intConstructor() throws Exception {
+ final int expected = 12;
+ PrivateConstructorInstantiationDemo tested = invokeConstructor(
+ PrivateConstructorInstantiationDemo.class, expected);
+ int actual = tested.getState();
+
+ assertEquals("Expected and actual did not match.", expected, actual);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PublicConstructorWithDependencyDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PublicConstructorWithDependencyDemoTest.java
new file mode 100644
index 0000000..c39fb83
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructor/PublicConstructorWithDependencyDemoTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.constructor;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.constructor.PublicConstructorWithDependencyDemo;
+
+import static org.easymock.EasyMock.createMock;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+
+/**
+ * Verifies that error messages are correct when the constructor cannot be found
+ * with partial mocking. This test asserts that the
+ * http://code.google.com/p/powertest/issues/detail?id=59 has been fixed.
+ *
+ */
+public class PublicConstructorWithDependencyDemoTest {
+
+ private Service serviceMock;
+
+ @Before
+ public void setUp() {
+ serviceMock = createMock(Service.class);
+ }
+
+ @After
+ public void tearDown() {
+ serviceMock = null;
+ }
+
+ /**
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testConstructorFound() throws Exception {
+ PublicConstructorWithDependencyDemo tested = createPartialMock(PublicConstructorWithDependencyDemo.class,
+ new String[] { "aMethod" }, serviceMock);
+
+ assertSame(serviceMock, tested.getService());
+ }
+
+ /**
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testConstructorNotFound() throws Exception {
+ try {
+ createPartialMock(PublicConstructorWithDependencyDemo.class, new String[] { "aMethod" }, serviceMock, "bad argument");
+ fail("Should throw ConstructorNotFoundException.");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + PublicConstructorWithDependencyDemo.class.getName()
+ + "' with parameter types: [ " + Service.class.getName() + ", " + String.class.getName() + " ].", e.getMessage());
+ }
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructorargs/ConstructorArgsDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructorargs/ConstructorArgsDemoTest.java
new file mode 100644
index 0000000..2813772
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/constructorargs/ConstructorArgsDemoTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.constructorargs;
+
+import org.easymock.ConstructorArgs;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.constructorargs.ConstructorArgsDemo;
+
+import java.lang.reflect.Constructor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This test demonstrates the ability to invoke a specific constructor after
+ * creating the mock object.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ConstructorArgsDemo.class)
+public class ConstructorArgsDemoTest {
+
+ @Test
+ public void testGetTheSecret_noConstructor() throws Exception {
+ ConstructorArgsDemo tested = createMock(ConstructorArgsDemo.class);
+ assertNull(Whitebox.getInternalState(tested, "secret", ConstructorArgsDemo.class));
+ }
+
+ @Test
+ public void testGetTheSecret_defaultConstructor() throws Exception {
+ final Constructor<ConstructorArgsDemo> constructor = ConstructorArgsDemo.class.getConstructor((Class<?>[]) null);
+ ConstructorArgsDemo tested = createMock(ConstructorArgsDemo.class, new ConstructorArgs(constructor));
+ assertEquals("default", Whitebox.getInternalState(tested, "secret", ConstructorArgsDemo.class));
+ }
+
+ @Test
+ public void testGetTheSecret_stringConstructor() throws Exception {
+ final String expected = "my own secret";
+ ConstructorArgsDemo tested = createMock(ConstructorArgsDemo.class, expected);
+ assertEquals(expected, Whitebox.getInternalState(tested, "secret", ConstructorArgsDemo.class));
+ }
+
+ @Test
+ public void testGetTheSecret_stringConstructorAndMockedPrivateSecret() throws Exception {
+ final String originalSecret = "my own secret";
+ ConstructorArgsDemo tested = createPartialMock(ConstructorArgsDemo.class, new String[] { "theSecretIsPrivate" }, originalSecret);
+ assertEquals(originalSecret, Whitebox.getInternalState(tested, "secret", ConstructorArgsDemo.class));
+
+ final String myNewSecret = "my new secret";
+ expectPrivate(tested, "theSecretIsPrivate").andReturn(myNewSecret);
+
+ replay(tested);
+
+ final String actual = tested.getTheSecret();
+
+ verify(tested);
+
+ assertEquals(myNewSecret, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/easymock/EasyMockAndPowerMockMixTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/easymock/EasyMockAndPowerMockMixTest.java
new file mode 100644
index 0000000..4169d74
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/easymock/EasyMockAndPowerMockMixTest.java
@@ -0,0 +1,38 @@
+package samples.junit4.easymock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.Service;
+import samples.privatefield.SimplePrivateFieldServiceClass;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.reflect.Whitebox.setInternalState;
+
+/**
+ * This test verifies that you can mix EasyMock and PowerMock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("samples.privatefield.SimplePrivateFieldServiceClass")
+public class EasyMockAndPowerMockMixTest {
+
+ @Test
+ public void testSimplePrivateFieldServiceClass() throws Exception {
+ SimplePrivateFieldServiceClass tested = new SimplePrivateFieldServiceClass();
+ Service serviceMock = createMock(Service.class);
+ setInternalState(tested, "service", serviceMock, SimplePrivateFieldServiceClass.class);
+
+ final String expected = "Hello world!";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replay(serviceMock);
+ final String actual = tested.useService();
+
+ verify(serviceMock);
+
+ assertEquals(expected, actual);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/enummocking/EnumMockingTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/enummocking/EnumMockingTest.java
new file mode 100644
index 0000000..24a5a65
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/enummocking/EnumMockingTest.java
@@ -0,0 +1,32 @@
+package samples.junit4.enummocking;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.enummocking.MyEnum;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MyEnum.class)
+public class EnumMockingTest {
+
+ @Test
+ public void assertMockingOfStaticMethodInEnumWorks() throws Exception {
+ final String expected = "something else";
+ mockStatic(MyEnum.class);
+
+ expect(MyEnum.getString()).andReturn(expected);
+
+ replayAll();
+
+ final String actual = MyEnum.getString();
+
+ verifyAll();
+
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/equalswithgetclass/EqualsWithGetClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/equalswithgetclass/EqualsWithGetClassTest.java
new file mode 100644
index 0000000..23db334
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/equalswithgetclass/EqualsWithGetClassTest.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.equalswithgetclass;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.MockGateway;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.equalswithgetclass.EqualsWithGetClass;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+
+/**
+ * Demonstrates that PowerMock ignores the call to getClass by default.
+ * Demonstrates that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=190">issue 190</a>
+ * is resolved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(EqualsWithGetClass.class)
+public class EqualsWithGetClassTest {
+
+ @Test
+ public void callingGetClassOnAMockWorksWhenTheCallWasUnexpected() throws Exception {
+ EqualsWithGetClass mock1 = createMock(EqualsWithGetClass.class);
+ replayAll();
+ assertTrue(mock1.getClass().getName().startsWith(EqualsWithGetClass.class.getName()));
+ }
+
+ @Test(expected = AssertionError.class)
+ public void callingGetClassOnAMockFailsWhenTheCallWasUnexpectedAndMockStandardMethodsIsSet() throws Exception {
+ try {
+ EqualsWithGetClass mock1 = createMock(EqualsWithGetClass.class);
+ MockGateway.MOCK_GET_CLASS_METHOD = true;
+ replayAll();
+ mock1.getClass();
+ } finally {
+ MockGateway.MOCK_GET_CLASS_METHOD = false;
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java
new file mode 100644
index 0000000..43567fc
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate new instance mocking using expectNew(..).
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class ExpectNewDemoTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replay(myClassMock, MyClass.class);
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock, MyClass.class);
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ expectNew(MyClass.class).andThrow(new RuntimeException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testPreviousProblemsWithByteCodeManipulation() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+ expect(myClassMock1.getMessage()).andReturn("Hello");
+ expect(myClassMock1.getMessage()).andReturn("World");
+ replay(myClassMock1);
+ assertEquals("Hello", myClassMock1.getMessage());
+ assertEquals("World", myClassMock1.getMessage());
+ verify(myClassMock1);
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ MyClass myClassMock2 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1);
+ expectNew(MyClass.class).andReturn(myClassMock2);
+
+ expect(myClassMock1.getMessage()).andReturn("Hello ");
+ expect(myClassMock2.getMessage()).andReturn("World");
+
+ replay(myClassMock1, myClassMock2, MyClass.class);
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock1, myClassMock2, MyClass.class);
+
+ assertEquals("Hello World", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.simpleMultipleNew();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleMultipleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_lowerBoundLessThan0() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ try {
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-20, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertEquals("minimum must be >= 0", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThan0() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-1, -2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThanLowerBound() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(10, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_OK() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(1, 5);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_anyTimes() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).anyTimes();
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_notWithinRange() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(5, 7);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: between 5 and 7, actual: 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ expectNew(DataInputStream.class, new Object[] { null }).andThrow(new RuntimeException("error"));
+
+ replay(ExpectNewDemo.class, DataInputStream.class);
+
+ InputStream stream = tested.alternativePath();
+
+ verify(ExpectNewDemo.class, DataInputStream.class);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ expectNew(VarArgsConstructorDemo.class, firstString, secondString).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllMessages()).andReturn(new String[] { firstString, secondString });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ expectNew(VarArgsConstructorDemo.class, object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = createMock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ expectNew(VarArgsConstructorDemo.class, serviceSubTypeInstance, serviceMock).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllServices()).andReturn(new Service[] { serviceMock });
+
+ replay(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verify(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, aryEq(byteArrayOne), aryEq(byteArrayTwo)).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo, byteArrayThree).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ try {
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "\n Unexpected constructor call samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 4):"
+ + "\n samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 2): expected: 1, actual: 0",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.makeDate();
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertTrue(e.getMessage().contains(MyClass.class.getName() + "(): expected: 1, actual: 0"));
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java
new file mode 100644
index 0000000..ad46086
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java
@@ -0,0 +1,28 @@
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewOfFinalSystemClassDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExpectNewOfFinalSystemClassDemo.class)
+public class ExpectNewOfFinalSystemClassTest {
+
+ @Test
+ public void assertThatExpectNewWorksForFinalSystemClasses() throws Exception {
+ String mock = createMock(String.class);
+
+ expectNew(String.class, "My String").andReturn(mock);
+ expect(mock.charAt(0)).andReturn('o');
+
+ replayAll();
+ assertEquals('o', new ExpectNewOfFinalSystemClassDemo().getFirstChar());
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/MockDateTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/MockDateTest.java
new file mode 100644
index 0000000..ed81b84
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/MockDateTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.expectnew;
+
+import junit.framework.Assert;
+import org.easymock.EasyMock;
+import org.easymock.internal.MocksControl;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+
+import java.lang.reflect.Method;
+import java.util.Date;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { ExpectNewDemo.class })
+public class MockDateTest {
+
+ @Test
+ public void testMockDate() throws Exception {
+ Date someDate = new Date();
+ Date date = PowerMock.createMock(Date.class);
+ EasyMock.expect(date.after(someDate)).andReturn(false);
+
+ PowerMock.replay(date);
+
+ date.after(someDate);
+
+ PowerMock.verify(date);
+ }
+
+ @Test
+ public void testMockDateWithEasyMock() throws Exception {
+ Date someDate = new Date();
+ MocksControl c = (MocksControl) org.easymock.EasyMock.createControl();
+ Date date = c.createMock(Date.class);
+ EasyMock.expect(date.after(someDate)).andReturn(false);
+
+ PowerMock.replay(date);
+
+ date.after(someDate);
+
+ PowerMock.verify(date);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testMockDateWithEasyMockFails() {
+ Date someDate = new Date();
+ MocksControl c = (MocksControl) org.easymock.EasyMock.createControl();
+ Date date = c.createMock(null, Date.class, null);
+ EasyMock.expect(date.after(someDate)).andReturn(false);
+ Assert.fail("EasyMock with no methods mocked should not be possible to mock");
+ }
+
+ @Test
+ public void testExpectNewDate() throws Exception {
+ Date someDate = new Date();
+ long time = someDate.getTime();
+ PowerMock.expectNew(Date.class).andReturn(someDate);
+
+ PowerMock.replay(Date.class);
+
+ Assert.assertEquals(time, new ExpectNewDemo().makeDate().getTime());
+
+ PowerMock.verify(Date.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperDemoTest.java
new file mode 100644
index 0000000..aebde49
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperDemoTest.java
@@ -0,0 +1,42 @@
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.exceptions.TooManyConstructorsFoundException;
+import samples.expectnew.PrimitiveAndWrapperDemo;
+
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.powermock.api.easymock.PowerMock.createMockAndExpectNew;
+
+/**
+ * Unit test for the {@link PrimitiveAndWrapperDemo} class.
+ */
+ at RunWith(PowerMockRunner.class)
+public class PrimitiveAndWrapperDemoTest {
+
+ @Test
+ public void testWhenConstructorCannotBeDetermined() throws Exception {
+ try {
+ createMockAndExpectNew(PrimitiveAndWrapperDemo.class, 2);
+ fail("Should throw TooManyConstructorsFoundException");
+ } catch (TooManyConstructorsFoundException e) {
+ assertThat(e.getMessage(), containsString("Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to."
+ + "\nMatching constructors in class samples.expectnew.PrimitiveAndWrapperDemo were:\n"));
+ assertThat(e.getMessage(), containsString("samples.expectnew.PrimitiveAndWrapperDemo( java.lang.Integer.class )\n"));
+ assertThat(e.getMessage(), containsString("samples.expectnew.PrimitiveAndWrapperDemo( int.class )\n"));
+ }
+ }
+
+ @Test
+ public void testWrapperConstructor() throws Exception {
+ createMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { Integer.class }, 2);
+ }
+
+ @Test
+ public void testPrimitiveConstructor() throws Exception {
+ createMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { int.class }, 2);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperUserTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperUserTest.java
new file mode 100644
index 0000000..9779cb5
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectnew/PrimitiveAndWrapperUserTest.java
@@ -0,0 +1,62 @@
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.PrimitiveAndWrapperDemo;
+import samples.expectnew.PrimitiveAndWrapperUser;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit test for the {@link PrimitiveAndWrapperUser} class.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PrimitiveAndWrapperUser.class)
+public class PrimitiveAndWrapperUserTest {
+
+ @Test
+ public void testNewWithStrictMocking_ok() throws Exception {
+ PrimitiveAndWrapperDemo mock1 = createStrictMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { Integer.class }, 42);
+ PrimitiveAndWrapperDemo mock2 = createStrictMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { int.class }, 21);
+
+ expect(mock1.getMyInt()).andReturn(10);
+ expect(mock2.getMyInt()).andReturn(21);
+
+ replayAll();
+
+ assertEquals(31, new PrimitiveAndWrapperUser().useThem());
+
+ verifyAll();
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testNewWithStrictMocking_notOk() throws Exception {
+ PrimitiveAndWrapperDemo mock2 = createStrictMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { int.class }, 21);
+ PrimitiveAndWrapperDemo mock1 = createStrictMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { Integer.class }, 42);
+
+ expect(mock1.getMyInt()).andReturn(10);
+ expect(mock2.getMyInt()).andReturn(21);
+
+ replayAll();
+
+ assertEquals(31, new PrimitiveAndWrapperUser().useThem());
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithNiceMocking() throws Exception {
+ PrimitiveAndWrapperDemo mock = createNiceMockAndExpectNew(PrimitiveAndWrapperDemo.class, new Class<?>[] { Integer.class }, 42);
+ expect(mock.getMyInt()).andReturn(2);
+
+ replayAll();
+
+ assertEquals(2, new PrimitiveAndWrapperUser().useThem());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectvoid/ExpectVoidDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectvoid/ExpectVoidDemoTest.java
new file mode 100644
index 0000000..3514a43
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/expectvoid/ExpectVoidDemoTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.expectvoid;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.expectvoid.ExpectVoidDemo;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExpectVoidDemo.class)
+public class ExpectVoidDemoTest {
+
+ @Test
+ public void testInvokeAPrivateVoidMethod() throws Exception {
+ final String methodToMock = "privateInvoke";
+ ExpectVoidDemo tested = createPartialMock(ExpectVoidDemo.class, methodToMock);
+
+ final int expected = 112;
+
+ expectPrivate(tested, methodToMock, expected).times(1);
+
+ replay(tested);
+
+ tested.invokeAPrivateVoidMethod(expected);
+
+ verify(tested);
+ }
+
+ @Test
+ public void testInvokeAPrivateVoidMethod_usingPowerMockExpectLastCall()
+ throws Exception {
+ final String methodToMock = "privateInvoke";
+ ExpectVoidDemo tested = createPartialMock(ExpectVoidDemo.class, methodToMock);
+
+ final int expected = 112;
+
+ Whitebox.invokeMethod(tested, methodToMock, expected);
+ expectLastCall().times(1);
+
+ replay(tested);
+
+ tested.invokeAPrivateVoidMethod(expected);
+
+ verify(tested);
+ }
+
+ @Test
+ public void testInvokeAPrivateVoidMethod_usingEasyMockExpectLastCall()
+ throws Exception {
+ final String methodToMock = "privateInvoke";
+ ExpectVoidDemo tested = createPartialMock(ExpectVoidDemo.class, methodToMock);
+
+ final int expected = 112;
+
+ Whitebox.invokeMethod(tested, methodToMock, expected);
+ EasyMock.expectLastCall();
+
+ replay(tested);
+
+ tested.invokeAPrivateVoidMethod(expected);
+
+ verify(tested);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/FinalDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/FinalDemoTest.java
new file mode 100644
index 0000000..7bf8985
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/FinalDemoTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.finalmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate non-static final mocking.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoTest {
+
+ @Test
+ public void testSay() throws Exception {
+ FinalDemo tested = createMock(FinalDemo.class);
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ FinalDemo tested = createMock(FinalDemo.class);
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/MockingOfInstanceMethodsInFinalSystemClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/MockingOfInstanceMethodsInFinalSystemClassTest.java
new file mode 100644
index 0000000..1c813d3
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/MockingOfInstanceMethodsInFinalSystemClassTest.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.finalmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate non-static final mocking of instance methods in
+ * system classes.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MockingOfInstanceMethodsInFinalSystemClassTest.class)
+public class MockingOfInstanceMethodsInFinalSystemClassTest {
+
+ @Test
+ public void assertThatMockingOfInstanceMethodsInFinalSystemClassesWorks() throws Exception {
+ Long tested = createMock(Long.class);
+ expect(tested.longValue()).andReturn(22L);
+ replayAll();
+
+ assertEquals(22L, tested.longValue());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfInstanceMethodsInStringWorks() throws Exception {
+ String tested = createMock(String.class);
+ expect(tested.charAt(2)).andReturn('A');
+ replayAll();
+
+ assertEquals('A', tested.charAt(2));
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfInstanceMethodsInFinalSystemClassesWhenNotInvokingConstructorWorks()
+ throws Exception {
+ Long tested = createPartialMock(Long.class, "doubleValue");
+ expect(tested.doubleValue()).andReturn(54d);
+ replayAll();
+
+ assertEquals(0, tested.longValue());
+ assertEquals(54d, tested.doubleValue(), 0.0d);
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfInstanceMethodsInFinalSystemClassesWhenNotInvokingNonDefaultConstructorWorks()
+ throws Exception {
+ Long tested = createPartialMock(Long.class, new String[] { "doubleValue" }, 27L);
+ expect(tested.doubleValue()).andReturn(54d);
+ replayAll();
+
+ assertEquals(27L, tested.longValue());
+ assertEquals(54d, tested.doubleValue(), 0.0d);
+
+ verifyAll();
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/NoDuplicateTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/NoDuplicateTest.java
new file mode 100644
index 0000000..0bb53f9
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/finalmocking/NoDuplicateTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.finalmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This test demonstrates that the issue at
+ * http://code.google.com/p/powertest/issues/detail?id=63 is solved.
+ *
+ * <p>
+ * The bug was that if there were only one test case and the
+ * <code>@PrepareForTest</code> annotation was placed at the test method instead
+ * of the class the PowerMock JUnit runner would detect an extra test case.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+public class NoDuplicateTest {
+
+ @Test
+ @PrepareForTest(FinalDemo.class)
+ public void assertThatPrepareForTestAnnotationAtMethodLevelButNotClassLevelWorks() throws Exception {
+ FinalDemo tested = createMock(FinalDemo.class);
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/hashcode/PowerMockUsesIdentityHashMapToStoreMocks.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/hashcode/PowerMockUsesIdentityHashMapToStoreMocks.java
new file mode 100644
index 0000000..3a22af7
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/hashcode/PowerMockUsesIdentityHashMapToStoreMocks.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.hashcode;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.hashcode.HashCodeInitializedInCtor;
+
+import static org.powermock.api.easymock.PowerMock.createMock;
+
+ at RunWith(PowerMockRunner.class)
+public class PowerMockUsesIdentityHashMapToStoreMocks {
+
+ @Test
+ public void storesObjectsToAutomaticallyReplayAndVerifyToAnIdentityHashMap()throws Exception {
+ createMock(HashCodeInitializedInCtor.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/interfacefieldchange/ChangeValueOfStaticFinalFieldInInterfacesDefect.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/interfacefieldchange/ChangeValueOfStaticFinalFieldInInterfacesDefect.java
new file mode 100644
index 0000000..d5e2c23
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/interfacefieldchange/ChangeValueOfStaticFinalFieldInInterfacesDefect.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.interfacefieldchange;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.interfacefieldchange.InterfaceWithStaticFinalField;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test asserts that it's possible for PowerMock to modify static final
+ * fields in Interfaces.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { InterfaceWithStaticFinalField.class })
+public class ChangeValueOfStaticFinalFieldInInterfacesDefect {
+
+ @Test
+ public void assertThatStaticFinalFieldValuesInInterfacesAreChangable() throws Exception {
+ final String value = "new value";
+ Whitebox.setInternalState(InterfaceWithStaticFinalField.class, value);
+ assertEquals(value, Whitebox.getInternalState(InterfaceWithStaticFinalField.class, String.class));
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/java/MockClassesInsideJavaPackage.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/java/MockClassesInsideJavaPackage.java
new file mode 100644
index 0000000..1d6f2fc
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/java/MockClassesInsideJavaPackage.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.java;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.java.ClassInsideJavaPackage;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ClassInsideJavaPackage.class)
+public class MockClassesInsideJavaPackage {
+
+ @Test
+ public void allowsMockingOfClassesInsidePackageContainingJava() {
+ ClassInsideJavaPackage mock = createMock(ClassInsideJavaPackage.class);
+ expect(mock.mockMe()).andReturn("mocked");
+
+ replayAll();
+
+ assertEquals("mocked", mock.mockMe());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/largemethod/LargeMethodTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/largemethod/LargeMethodTest.java
new file mode 100644
index 0000000..5ede28a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/largemethod/LargeMethodTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.junit4.largemethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.largemethod.MethodExceedingJvmLimit;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.method;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MethodExceedingJvmLimit.class)
+public class LargeMethodTest {
+
+ @Test
+ public void largeMethodShouldBeOverridden() {
+ try {
+ MethodExceedingJvmLimit.init();
+ fail("Method should be overridden and exception should be thrown");
+ } catch (Exception e) {
+ assertSame(IllegalAccessException.class, e.getClass());
+ assertTrue(e.getMessage().contains("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeSuppressed() {
+ suppress(method(MethodExceedingJvmLimit.class, "init"));
+ assertNull("Suppressed method should return: null", MethodExceedingJvmLimit.init());
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeMocked() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ expect(MethodExceedingJvmLimit.init()).andReturn("ok");
+ replayAll();
+ assertEquals("Mocked method should return: ok", "ok", MethodExceedingJvmLimit.init());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void largeMethodShouldBeAbleToBeMockedAndThrowException() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ expect(MethodExceedingJvmLimit.init()).andThrow(new IllegalStateException());
+ replayAll();
+ MethodExceedingJvmLimit.init();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/misc/PrivateInnerInterfacesInTestClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/misc/PrivateInnerInterfacesInTestClassTest.java
new file mode 100644
index 0000000..e1c479f
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/misc/PrivateInnerInterfacesInTestClassTest.java
@@ -0,0 +1,27 @@
+package samples.junit4.misc;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { PrivateInnerInterfacesInTestClassTest.class })
+public class PrivateInnerInterfacesInTestClassTest {
+
+ @Test
+ public void privateInterfacesCanBeLoadedAndBytcodeManipulatedByPowerMock() throws Exception {
+ InnerInterface innerInterface = new InnerInterface() {
+ public String aMethod() {
+ return "ok";
+ }
+ };
+ assertEquals("ok", innerInterface.aMethod());
+ }
+
+ private interface InnerInterface {
+ String aMethod();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyUsageExampleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyUsageExampleTest.java
new file mode 100644
index 0000000..e7bfdc5
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyUsageExampleTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.mockpolicy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.mockpolicy.ResultCalculator;
+import samples.mockpolicy.SomeClassWithAMethod;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * A simple example of a mock policy that stubs out a method call.
+ */
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(MockPolicyExample.class)
+public class MockPolicyUsageExampleTest {
+
+ @Test
+ public void exampleOfStubbingOutCallsInParentClass() throws Exception {
+ SomeClassWithAMethod tested = new SomeClassWithAMethod();
+ assertEquals(8.0d, tested.getResult(), 0.0d);
+ }
+}
+
+class MockPolicyExample implements PowerMockPolicy {
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(ResultCalculator.class.getName());
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ Method calculateMethod = Whitebox.getMethod(ResultCalculator.class);
+ settings.stubMethod(calculateMethod, 4);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithExpectationsTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithExpectationsTest.java
new file mode 100644
index 0000000..25f24f7
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithExpectationsTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.mockpolicy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.mockpolicy.ResultCalculator;
+import samples.mockpolicy.SimpleClassWithADependency;
+
+import java.lang.reflect.Method;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(MockPolicyExpectationsExample.class)
+public class MockPolicyWithExpectationsTest {
+
+ @Test
+ public void mockPolicyWithExpectationsWorks() throws Exception {
+ final SimpleClassWithADependency tested = new SimpleClassWithADependency();
+ Whitebox.setInternalState(tested, new ResultCalculator(5));
+
+ assertEquals(2.0, tested.getResult(), 0.0);
+
+ verifyAll();
+ }
+}
+
+class MockPolicyExpectationsExample implements PowerMockPolicy {
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(ResultCalculator.class.getName());
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ final ResultCalculator calculatorMock = createMock(ResultCalculator.class);
+ expect(calculatorMock.calculate()).andReturn(2.0);
+
+ replay(calculatorMock);
+
+ Method calculateMethod = Whitebox.getMethod(ResultCalculator.class, "calculate");
+ settings.stubMethod(calculateMethod, calculatorMock.calculate());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithInvocationHandlerTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithInvocationHandlerTest.java
new file mode 100644
index 0000000..3f75a6d
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/MockPolicyWithInvocationHandlerTest.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.mockpolicy;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.mockpolicy.ResultCalculator;
+import samples.mockpolicy.SimpleClassWithADependency;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(MockPolicyInvocationHandlerExample.class)
+public class MockPolicyWithInvocationHandlerTest {
+
+ @Test
+ public void mockPolicyWithInvocationHandlerWorks() throws Exception {
+ final SimpleClassWithADependency tested = new SimpleClassWithADependency();
+ Whitebox.setInternalState(tested, new ResultCalculator(0));
+
+ assertEquals(1.0, tested.getResult(), 0.0);
+
+ verifyAll();
+ }
+}
+
+class MockPolicyInvocationHandlerExample implements PowerMockPolicy {
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addFullyQualifiedNamesOfClassesToLoadByMockClassloader(ResultCalculator.class.getName());
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ settings.proxyMethod(method(ResultCalculator.class), new InvocationHandler() {
+
+ @Override
+ public Object invoke(Object object, Method method, Object[] args) throws Throwable {
+ final double result = (Double) method.invoke(object, args);
+ return result + 1.0;
+ }
+ });
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkMockPolicy.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkMockPolicy.java
new file mode 100644
index 0000000..67147a9
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkMockPolicy.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.mockpolicy.frameworkexample;
+
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.reflect.Whitebox;
+import samples.mockpolicy.frameworkexample.NativeResult;
+import samples.mockpolicy.frameworkexample.SimpleFramework;
+
+import java.lang.reflect.Method;
+
+public class SimpleFrameworkMockPolicy implements PowerMockPolicy {
+
+ public static final String NATIVE_RESULT_VALUE = "result";
+
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ settings.addStaticInitializersToSuppress("samples.mockpolicy.frameworkexample.SimpleFramework");
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ final Method doNativeStuffMethod = Whitebox.getMethod(SimpleFramework.class, String.class);
+ NativeResult nativeResult = new NativeResult(NATIVE_RESULT_VALUE);
+ settings.stubMethod(doNativeStuffMethod, nativeResult);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkUserTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkUserTest.java
new file mode 100644
index 0000000..e7d58da
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/mockpolicy/frameworkexample/SimpleFrameworkUserTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.mockpolicy.frameworkexample;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.mockpolicy.frameworkexample.SimpleFrameworkUser;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(PowerMockRunner.class)
+ at MockPolicy(SimpleFrameworkMockPolicy.class)
+public class SimpleFrameworkUserTest {
+
+ @Test
+ public void testPerformComplexOperation() throws Exception {
+ SimpleFrameworkUser tested = new SimpleFrameworkUser();
+ assertEquals(SimpleFrameworkMockPolicy.NATIVE_RESULT_VALUE, tested.performComplexOperation("some complex stuff"));
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/multireplayverify/MultiReplayVerifyTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/multireplayverify/MultiReplayVerifyTest.java
new file mode 100644
index 0000000..1557c6b
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/multireplayverify/MultiReplayVerifyTest.java
@@ -0,0 +1,60 @@
+package samples.junit4.multireplayverify;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+import samples.newmocking.MyClass;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Asserts that it's ok the manually replay a mock and then use replayAll(). The
+ * same regards verify and verifyAll.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExpectNewDemo.class)
+public class MultiReplayVerifyTest {
+
+ @Test
+ public void replyFollowedByReplayAllIsAllowed() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replay(MyClass.class);
+ replayAll();
+
+ String actual = tested.getMessage();
+
+ verifyAll();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void verifyFollowedByVerifyAllIsAllowed() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replayAll();
+
+ String actual = tested.getMessage();
+
+ verify(MyClass.class);
+ verifyAll();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nativemocking/NativeMockingSampleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nativemocking/NativeMockingSampleTest.java
new file mode 100644
index 0000000..261dd71
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nativemocking/NativeMockingSampleTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.nativemocking;
+
+import org.junit.Test;
+import samples.nativemocking.NativeMockingSample;
+import samples.nativemocking.NativeService;
+
+import static org.easymock.EasyMock.*;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test demonstrates that it's possible to mock native methods using plain
+ * EasyMock class extensions.
+ */
+public class NativeMockingSampleTest {
+
+ @Test
+ public void testMockNative() throws Exception {
+ NativeService nativeServiceMock = createMock(NativeService.class);
+ NativeMockingSample tested = new NativeMockingSample(nativeServiceMock);
+
+ final String expectedParameter = "question";
+ final String expectedReturnValue = "answer";
+ expect(nativeServiceMock.invokeNative(expectedParameter)).andReturn(expectedReturnValue);
+
+ replay(nativeServiceMock);
+
+ assertEquals(expectedReturnValue, tested.invokeNativeMethod(expectedParameter));
+
+ verify(nativeServiceMock);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/newmocking/StupidNewTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/newmocking/StupidNewTest.java
new file mode 100644
index 0000000..4673072
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/newmocking/StupidNewTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.newmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.newmocking.MyClass;
+import samples.newmocking.StupidNew;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate new instance mocking.
+ *
+ * @author Johan Haleby
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, StupidNew.class })
+public class StupidNewTest {
+
+ @Test
+ public void testGetMessage() throws Exception {
+ StupidNew tested = new StupidNew();
+
+ MyClass myClassMock = createMockAndExpectNew(MyClass.class);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ StupidNew tested = new StupidNew();
+
+ MyClass myClassMock = createMockAndExpectNew(MyClass.class);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ StupidNew tested = new StupidNew();
+
+ MyClass myClassMock = createMockAndExpectNew(MyClass.class);
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replay(myClassMock, MyClass.class);
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock, MyClass.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nice/NiceDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nice/NiceDemoTest.java
new file mode 100644
index 0000000..5794daf
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/nice/NiceDemoTest.java
@@ -0,0 +1,29 @@
+package samples.junit4.nice;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.nice.NiceDemo;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This is a simple test case for the {@link NiceDemo} class that demonstrates
+ * that strict method mocking works.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+public class NiceDemoTest {
+
+ @Test
+ public void testCallAThenB_noExpectations() throws Exception {
+ NiceDemo tested = createNicePartialMock(NiceDemo.class, "A", "B");
+
+ replay(tested);
+
+ tested.callAThenB();
+
+ verify(tested);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/NoAnnotationUsageTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/NoAnnotationUsageTest.java
new file mode 100644
index 0000000..0539779
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/NoAnnotationUsageTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test case that demonstrates the ability to run test cases not annotated with
+ * {@link Test} when extending from {@link TestCase} using JUnit 4.4.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class NoAnnotationUsageTest extends TestCase {
+
+ public void testGetMessage() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class, "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+
+ public void testGetMessage2() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class, "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java
new file mode 100644
index 0000000..61d74d3
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenExtendingTestCaseTest.java
@@ -0,0 +1,30 @@
+package samples.junit4.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+ at RunWith(PowerMockRunner.class)
+public class SetUpAndTearDownWhenExtendingTestCaseTest extends TestCase {
+ private static final String INITIAL_MESSAGE = "";
+ private static final String SET_UP_MESSAGE = "setUp";
+ private static final String TEST_MESSAGE = "test";
+
+ private static String CURRENT_MESSAGE = INITIAL_MESSAGE;
+
+ @Override
+ protected void setUp() throws Exception {
+ assertEquals(INITIAL_MESSAGE, CURRENT_MESSAGE);
+ CURRENT_MESSAGE = SET_UP_MESSAGE;
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ assertEquals(TEST_MESSAGE, CURRENT_MESSAGE);
+ }
+
+ public void testSomething() throws Exception {
+ assertEquals(SET_UP_MESSAGE, CURRENT_MESSAGE);
+ CURRENT_MESSAGE = TEST_MESSAGE;
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java
new file mode 100644
index 0000000..b25258e
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpAndTearDownWhenNotExtendingTestCaseTest.java
@@ -0,0 +1,27 @@
+package samples.junit4.noannotation;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+ at RunWith(PowerMockRunner.class)
+public class SetUpAndTearDownWhenNotExtendingTestCaseTest {
+ private static final String INITIAL_MESSAGE = "";
+ private static String CURRENT_MESSAGE = INITIAL_MESSAGE;
+
+ public void setUp() throws Exception {
+ fail("Should not call setUp");
+ }
+
+ public void tearDown() throws Exception {
+ fail("Should not call tearDown");
+ }
+
+ @Test
+ public void testSomething() throws Exception {
+ assertEquals(INITIAL_MESSAGE, CURRENT_MESSAGE);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpIsOnlyCalledOnceWhenExtendingTestCaseTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpIsOnlyCalledOnceWhenExtendingTestCaseTest.java
new file mode 100644
index 0000000..b5d21a6
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/SetUpIsOnlyCalledOnceWhenExtendingTestCaseTest.java
@@ -0,0 +1,19 @@
+package samples.junit4.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.Before;
+
+public class SetUpIsOnlyCalledOnceWhenExtendingTestCaseTest extends TestCase {
+
+ private int state = 0;
+
+ @Before
+ @Override
+ public void setUp() throws Exception {
+ state++;
+ }
+
+ public void testSetupMethodIsOnlyCalledOnceWhenExtendingFromTestCase() throws Exception {
+ assertEquals(1, state);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/StringConstructorWorksWhenExtendingTestCase.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/StringConstructorWorksWhenExtendingTestCase.java
new file mode 100644
index 0000000..ea00e0c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/noannotation/StringConstructorWorksWhenExtendingTestCase.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.noannotation;
+
+import junit.framework.TestCase;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Demonstrates that the PowerMock JUnit runner works with single-arg string
+ * constructor. Asserts that issue <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=174">174</a> is
+ * fixed.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class StringConstructorWorksWhenExtendingTestCase extends TestCase {
+
+ public StringConstructorWorksWhenExtendingTestCase(String name) {
+ super(name);
+ }
+
+ public void testMockingStaticMethodWorksWhenStringArgConstructor() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/MethodWithSameNameButDifferentDefinitionTypeTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/MethodWithSameNameButDifferentDefinitionTypeTest.java
new file mode 100644
index 0000000..8e565be
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/MethodWithSameNameButDifferentDefinitionTypeTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.overloading;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+import samples.overloading.StaticAndInstanceMethodWithSameName;
+import samples.overloading.StaticAndInstanceMethodWithSameNameUser;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Demonstrates that PowerMock correctly methods that seam to be overloaded but
+ * differ because one is static and one is instance.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticAndInstanceMethodWithSameNameUser.class, StaticAndInstanceMethodWithSameName.class })
+public class MethodWithSameNameButDifferentDefinitionTypeTest {
+
+ @Test
+ public void mockGatewayCanInvokeInstanceMethodWhenClassContainsStaticAndInstanceMethodWithSameName() throws Exception {
+ final ChildA object = createMock(ChildA.class);
+ StaticAndInstanceMethodWithSameName mock = createMock(StaticAndInstanceMethodWithSameName.class);
+
+ expectNew(ChildA.class).andReturn(object);
+ mock.overloaded((Parent) object);
+ expectLastCall().once();
+
+ replayAll();
+
+ new StaticAndInstanceMethodWithSameNameUser().performInstaceInvocation(mock);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockGatewayCanInvokeStaticMethodWhenClassContainsStaticAndInstanceMethodWithSameName() throws Exception {
+ final Parent object = createMock(ChildA.class);
+
+ mockStatic(StaticAndInstanceMethodWithSameName.class);
+ expectNew(ChildA.class).andReturn((ChildA) object);
+ StaticAndInstanceMethodWithSameName.overloaded((ChildA) object);
+ expectLastCall().once();
+
+ replayAll();
+
+ new StaticAndInstanceMethodWithSameNameUser().performStaticInvocation();
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/OverloadingDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/OverloadingDemoTest.java
new file mode 100644
index 0000000..7443e21
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/overloading/OverloadingDemoTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.overloading;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+import samples.overloading.OverloadedMethodsExample;
+import samples.overloading.OverloadingDemo;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Demonstrates that PowerMock correctly invoke overloaded methods from the
+ * MockGateway.
+ * href="http://code.google.com/p/powermock/issues/detail?id=229">229</a> is
+ * solved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({ OverloadedMethodsExample.class, OverloadingDemo.class })
+public class OverloadingDemoTest {
+
+ @Test
+ public void mockGatewayFindsBestOverloadedMethodCandidateWhenOnlyOneArgument() throws Exception {
+ final Parent object = createMock(ChildA.class);
+
+ mockStatic(OverloadedMethodsExample.class);
+
+ OverloadedMethodsExample.overloadedMethodWithOneArgument(object);
+ expectLastCall().once();
+
+ expectNew(ChildA.class).andReturn((ChildA) object);
+
+ replayAll();
+
+ final OverloadingDemo demo = new OverloadingDemo();
+ demo.performSingleOverloadedArgumentTest();
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockGatewayFindsBestOverloadedMethodCandidateWhenBothArgumentSame() throws Exception {
+ final Parent child = createMock(ChildA.class);
+
+ mockStatic(OverloadedMethodsExample.class);
+
+ OverloadedMethodsExample.overloadedMethodWithTwoArguments(child, child);
+ expectLastCall().once();
+
+ expectNew(ChildA.class).andReturn((ChildA) child).times(2);
+
+ replayAll();
+
+ final OverloadingDemo demo = new OverloadingDemo();
+ demo.performMethodOverloadTestWhenBothArgumentSame();
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockGatewayFindsBestOverloadedMethodCandidateWhenOneArgumentSameAndOneDifferent() throws Exception {
+ final Parent child = createMock(ChildA.class);
+ final Parent parent = createMock(Parent.class);
+
+ mockStatic(OverloadedMethodsExample.class);
+
+ OverloadedMethodsExample.overloadedMethodWithTwoArguments(parent, child);
+ expectLastCall().once();
+
+ expectNew(ChildA.class).andReturn((ChildA) child);
+ expectNew(Parent.class).andReturn(parent);
+
+ replayAll();
+
+ final OverloadingDemo demo = new OverloadingDemo();
+ demo.performMethodOverloadTestWithOneArgumentSameAndOneDiffernt();
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoTest.java
new file mode 100644
index 0000000..a5d058c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.partialmocking.MockSelfDemo;
+import samples.partialmocking.MockSelfWithNoDefaultConstructorDemo;
+
+import java.sql.Connection;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MockSelfDemo.class)
+public class MockSelfDemoTest {
+
+ private MockSelfDemo tested;
+
+ @Test
+ public void testMockMultiple_ok() throws Exception {
+ tested = createPartialMock(MockSelfDemo.class, "aMethod2", "getString");
+
+ tested.aMethod2();
+ expectLastCall().times(1);
+
+ final String expected = "Hello altered world";
+ expect(tested.getString("world")).andReturn(expected);
+
+ replay(tested);
+
+ String actual = tested.aMethod();
+
+ verify(tested);
+
+ assertEquals("Result ought to be \"Hello altered world\".", expected, actual);
+ }
+
+ @Test
+ public void testMockMultiple_sameName() throws Exception {
+ tested = createPartialMock(MockSelfDemo.class, "getString");
+
+ final String firstString = "A message: ";
+ expectPrivate(tested, "getString").andReturn(firstString);
+
+ final String secondString = "altered world";
+ expect(tested.getString("world2")).andReturn(secondString);
+ final String expected = firstString + secondString;
+
+ replay(tested);
+
+ String actual = tested.getTwoStrings();
+
+ verify(tested);
+
+ assertEquals("Result ought to be \"A message:Hello altered world\".", expected, actual);
+ }
+
+ @Test
+ public void testMockSingleMethod() throws Exception {
+ tested = createPartialMock(MockSelfDemo.class, "timesTwo", int.class);
+
+ final int expectedInt = 2;
+ final int expectedInteger = 8;
+ expect(tested.timesTwo(4)).andReturn(expectedInt);
+
+ replay(tested);
+
+ int actualInt = tested.timesTwo(4);
+ int actualInteger = tested.timesTwo(new Integer(4));
+
+ verify(tested);
+
+ assertEquals(expectedInt, actualInt);
+ assertEquals(expectedInteger, actualInteger);
+ }
+
+ @Test
+ public void testMockAllExcept_parametersDefined() throws Exception {
+ tested = createPartialMockForAllMethodsExcept(MockSelfDemo.class, "getString2", String.class);
+
+ final String expected = "Hello altered world";
+ expect(tested.getString2()).andReturn(expected);
+
+ replay(tested);
+ assertEquals(expected, tested.getString2());
+ assertEquals("Hello string", tested.getString2("string"));
+ verify(tested);
+ }
+
+ @Test
+ public void testMockAllExcept_single() throws Exception {
+ tested = createPartialMockForAllMethodsExcept(MockSelfDemo.class, "aMethod");
+ tested.aMethod2();
+ expectLastCall().times(1);
+
+ final String expected = "Hello altered world";
+ expect(tested.getString("world")).andReturn(expected);
+
+ replay(tested);
+
+ String actual = tested.aMethod();
+
+ verify(tested);
+
+ assertEquals("Result ought to be \"Hello altered world\".", expected, actual);
+ }
+
+ @Test
+ public void testMockAllExcept_multiple() throws Exception {
+ tested = createPartialMockForAllMethodsExcept(MockSelfDemo.class, "timesTwo", "timesThree");
+
+ final String expected = "A new value";
+ expect(tested.getString2()).andReturn(expected);
+
+ replay(tested);
+
+ assertEquals(4, tested.timesTwo(2));
+ assertEquals(4, tested.timesTwo(new Integer(2)));
+ assertEquals(6, tested.timesThree(2));
+ assertEquals(expected, tested.getString2());
+
+ verify(tested);
+ }
+
+ @Test
+ public void testCreatePartialMockAndInvokeObjectConstructor() throws Exception {
+ tested = createPartialMock(MockSelfDemo.class, new String[] { "aMethod2", "getString" }, new Object());
+
+ tested.aMethod2();
+ expectLastCall().times(1);
+
+ final String expected = "Hello altered world";
+ expect(tested.getString("world")).andReturn(expected);
+
+ replay(tested);
+
+ String actual = tested.aMethod();
+
+ verify(tested);
+
+ assertEquals("Result ought to be \"Hello altered world\".", expected, actual);
+ }
+
+ @Test
+ public void testCreatePartialMockAndInvokeDefaultConstructor() throws Exception {
+ tested = createPartialMockAndInvokeDefaultConstructor(MockSelfDemo.class, "aMethod2", "getString");
+
+ tested.aMethod2();
+ expectLastCall().times(1);
+
+ final String expected = "Hello altered world";
+ expect(tested.getString("world")).andReturn(expected);
+
+ replay(tested);
+
+ String actual = tested.aMethod();
+
+ verify(tested);
+
+ assertEquals("Result ought to be \"Hello altered world\".", expected, actual);
+ }
+
+ @Test
+ public void partialMockingWithNullArgumentWorks() throws Exception {
+ final MockSelfDemo tested = createPartialMock(MockSelfDemo.class, "establishConnection");
+ Connection conn=null;
+ Whitebox.invokeMethod(tested, "establishConnection", conn);
+ }
+
+ @PrepareForTest(MockSelfWithNoDefaultConstructorDemo.class)
+ @Test
+ public void testCreatePartialMockAndInvokeDefaultConstructor_noDefaultConstructorFound() throws Exception {
+ try {
+ createPartialMockAndInvokeDefaultConstructor(MockSelfWithNoDefaultConstructorDemo.class, "aMethod2");
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("Failed to lookup constructor with parameter types [ <none> ] in class samples.partialmocking.MockSelfWithNoDefaultConstructorDemo.", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoWithSubClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoWithSubClassTest.java
new file mode 100644
index 0000000..95ec67a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/MockSelfDemoWithSubClassTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.MockSelfDemoWithSubClass;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MockSelfDemoWithSubClass.class)
+public class MockSelfDemoWithSubClassTest {
+
+ @Test
+ public void testMockPartialMethodInChildClass() throws Exception {
+ MockSelfDemoWithSubClass tested = createPartialMock(
+ MockSelfDemoWithSubClass.class, "getAMessage",
+ "getInternalMessage");
+
+ final String getAMessageMock = "Hello ";
+ final String getInternalMessageMock = "World!";
+ final String expected = getInternalMessageMock + getAMessageMock;
+
+ expect(tested.getAMessage()).andReturn(getAMessageMock);
+ expectPrivate(tested, "getInternalMessage").andReturn(
+ getInternalMessageMock);
+
+ replay(tested);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+
+ assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorTest.java
new file mode 100644
index 0000000..362c732
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.partialmocking;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import samples.partialmocking.PartialMockingWithConstructor;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+public class PartialMockingWithConstructorTest {
+
+ @Ignore("The initialize method is never invoked but is caught by the proxy. This is a possibly a bug in EasyMock class extensions?")
+ @Test
+ public void testPartialMock() throws Exception {
+
+ /*
+ * In the original test case PartialMockingWithConstructor had
+ * constructor arguments which I removed to slim down the test case,
+ * originally I was using the following method to create a partial mock.
+ * Regardless the same problem still occurs.
+ */
+ PartialMockingWithConstructor nationPartialMock = createPartialMockAndInvokeDefaultConstructor(PartialMockingWithConstructor.class, "touch");
+
+ /*
+ * The following method also causes the same problem.
+ */
+
+ // Nation nationPartialMock =
+ // createPartialMockAndInvokeDefaultConstructor(Nation.class,"touch");
+ replay(nationPartialMock);
+
+ // Uncommenting the following line has no effect on the test result.
+ // nationPartialMock.initialize();
+
+ verify(nationPartialMock);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorUsingEasyMockTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorUsingEasyMockTest.java
new file mode 100644
index 0000000..b1000f5
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/partialmocking/PartialMockingWithConstructorUsingEasyMockTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.partialmocking;
+
+import org.easymock.ConstructorArgs;
+import org.junit.Ignore;
+import org.junit.Test;
+import samples.partialmocking.PartialMockingWithConstructor;
+
+import java.lang.reflect.Method;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createMock;
+
+public class PartialMockingWithConstructorUsingEasyMockTest {
+
+ @SuppressWarnings("deprecation")
+ @Ignore("The initialize method is never invoked but is caught by the proxy. This is a possibly a bug in EasyMock class extensions?")
+ @Test
+ public void testPartialMock() throws Exception {
+
+ /*
+ * In the original test case PartialMockingWithConstructor had
+ * constructor arguments which I removed to slim down the test case,
+ * originally I was using the following method to create a partial mock.
+ * Regardless the same problem still occurs.
+ */
+ ConstructorArgs args = new ConstructorArgs(PartialMockingWithConstructor.class.getConstructor());
+ Method touchMethod = PartialMockingWithConstructor.class.getMethod("touch");
+
+ PartialMockingWithConstructor nationPartialMock = createMock(PartialMockingWithConstructor.class, args, touchMethod);
+
+ /*
+ * The following method also causes the same problem.
+ */
+
+ // Nation nationPartialMock =
+ // createPartialMockAndInvokeDefaultConstructor(Nation.class,"touch");
+ replay(nationPartialMock);
+
+ // Uncommenting the following line has no effect on the test result.
+ // nationPartialMock.initialize();
+
+ verify(nationPartialMock);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/PowerMockIgnoreAndPrepareForTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/PowerMockIgnoreAndPrepareForTest.java
new file mode 100644
index 0000000..421de0d
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/PowerMockIgnoreAndPrepareForTest.java
@@ -0,0 +1,30 @@
+package samples.junit4.powermockignore;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PowerMockIgnore("samples.*")
+ at PrepareForTest(StaticService.class)
+public class PowerMockIgnoreAndPrepareForTest {
+
+ @Test public void
+ powermock_ignore_annotation_and_prepare_for_test_annotation_can_be_combined() {
+ mockStatic(StaticService.class);
+ String expected = "qwe";
+ expect(StaticService.doStatic(5)).andReturn(expected);
+ replay(StaticService.class);
+
+ String actual = StaticService.doStatic(5);
+ assertEquals(expected, actual);
+ verify(StaticService.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/SomeJUnit4Tests.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/SomeJUnit4Tests.java
new file mode 100644
index 0000000..55e30ca
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/powermockignore/SomeJUnit4Tests.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.powermockignore;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+import samples.junit4.constructorargs.ConstructorArgsDemoTest;
+import samples.junit4.expectvoid.ExpectVoidDemoTest;
+import samples.junit4.finalmocking.FinalDemoTest;
+import samples.junit4.newmocking.StupidNewTest;
+import samples.junit4.noannotation.NoAnnotationUsageTest;
+import samples.junit4.partialmocking.MockSelfDemoTest;
+import samples.junit4.partialmocking.MockSelfDemoWithSubClassTest;
+import samples.junit4.prepareeverything.ExpectNewDemoUsingThePrepareEverythingAnnotationTest;
+import samples.junit4.privateandfinal.PrivateFinalTest;
+import samples.junit4.privatefield.MockSelfPrivateFieldServiceClassTest;
+import samples.junit4.privatefield.SimplePrivateFieldServiceClassTest;
+import samples.junit4.privatemocking.PrivateMethodDemoTest;
+import samples.junit4.simplereturn.SimpleReturnExampleUserTest;
+import samples.junit4.singleton.MockStaticTest;
+import samples.junit4.staticandinstance.StaticAndInstanceDemoTest;
+import samples.junit4.staticinitializer.StaticInitializerExampleTest;
+import samples.junit4.suppressconstructor.SuppressConstructorDemoTest;
+import samples.junit4.suppressconstructor.SuppressConstructorHierarchyDemoTest;
+import samples.junit4.suppressmethod.SuppressMethodTest;
+import samples.suppressconstructor.SuppressSpecificConstructorDemoTest;
+
+// This test verifies that the SuppressConstructorHierachyDemo works, issue http://code.google.com/p/powermock/issues/detail?id=43.
+
+ at RunWith(Suite.class)
+ at SuiteClasses( { ExpectVoidDemoTest.class, FinalDemoTest.class, MockSelfDemoTest.class, MockSelfDemoWithSubClassTest.class, StupidNewTest.class,
+ PrivateFinalTest.class, MockSelfPrivateFieldServiceClassTest.class, SimplePrivateFieldServiceClassTest.class, PrivateMethodDemoTest.class,
+ MockStaticTest.class, StaticAndInstanceDemoTest.class, SuppressMethodTest.class, SuppressConstructorDemoTest.class,
+ SuppressConstructorHierarchyDemoTest.class, SuppressSpecificConstructorDemoTest.class, ConstructorArgsDemoTest.class,
+ NoAnnotationUsageTest.class, SimpleReturnExampleUserTest.class, StaticInitializerExampleTest.class,
+ ExpectNewDemoUsingThePrepareEverythingAnnotationTest.class })
+public class SomeJUnit4Tests {
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/prepareeverything/ExpectNewDemoUsingThePrepareEverythingAnnotationTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/prepareeverything/ExpectNewDemoUsingThePrepareEverythingAnnotationTest.java
new file mode 100644
index 0000000..ac8bb0c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/prepareeverything/ExpectNewDemoUsingThePrepareEverythingAnnotationTest.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.prepareeverything;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareEverythingForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate new instance mocking using expectNew(..) with the
+ * {@link PrepareEverythingForTest} annotation and replayAll and verifyAll.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareEverythingForTest
+public class ExpectNewDemoUsingThePrepareEverythingAnnotationTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replayAll();
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyAll();
+ }
+
+ @PrepareEverythingForTest
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replayAll();
+
+ String actual = tested.getMessage();
+
+ verifyAll();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replayAll();
+
+ String actual = tested.getMessageWithArgument();
+
+ verifyAll();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replayAll();
+
+ tested.invokeVoidMethod();
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ expectNew(MyClass.class).andThrow(new RuntimeException(expectedFailMessage));
+
+ replayAll();
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyAll();
+ }
+
+ @Test
+ public void testPreviousProblemsWithByteCodeManipulation() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+ expect(myClassMock1.getMessage()).andReturn("Hello");
+ expect(myClassMock1.getMessage()).andReturn("World");
+ replayAll();
+ assertEquals("Hello", myClassMock1.getMessage());
+ assertEquals("World", myClassMock1.getMessage());
+ verifyAll();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ MyClass myClassMock2 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1);
+ expectNew(MyClass.class).andReturn(myClassMock2);
+
+ expect(myClassMock1.getMessage()).andReturn("Hello ");
+ expect(myClassMock2.getMessage()).andReturn("World");
+
+ replayAll();
+
+ final String actual = tested.multipleNew();
+
+ verifyAll();
+
+ assertEquals("Hello World", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replayAll();
+
+ tested.simpleMultipleNew();
+
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replayAll();
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyAll();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replayAll();
+ try {
+ tested.simpleMultipleNew();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replayAll();
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replayAll();
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replayAll();
+ tested.simpleSingleNew();
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replayAll();
+ tested.simpleSingleNew();
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replayAll();
+ tested.simpleMultipleNew();
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_lowerBoundLessThan0() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ try {
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-20, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertEquals("minimum must be >= 0", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThan0() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-1, -2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThanLowerBound() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(10, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_OK() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(1, 5);
+
+ replayAll();
+
+ tested.simpleMultipleNew();
+
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_anyTimes() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).anyTimes();
+
+ replayAll();
+
+ tested.simpleMultipleNew();
+
+ verifyAll();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_notWithinRange() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(5, 7);
+
+ replayAll();
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyAll();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: between 5 and 7, actual: 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ expectNew(DataInputStream.class, new Object[] { null }).andThrow(new RuntimeException("error"));
+
+ replayAll();
+
+ InputStream stream = tested.alternativePath();
+
+ verifyAll();
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replayAll();
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ verifyAll();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replayAll();
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ expectNew(VarArgsConstructorDemo.class, firstString, secondString).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllMessages()).andReturn(new String[] { firstString, secondString });
+
+ replayAll();
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ expectNew(VarArgsConstructorDemo.class, object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = createMock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ @Override
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ expectNew(VarArgsConstructorDemo.class, serviceSubTypeInstance, serviceMock).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllServices()).andReturn(new Service[] { serviceMock });
+
+ replayAll();
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, aryEq(byteArrayOne), aryEq(byteArrayTwo)).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo, byteArrayThree).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replayAll();
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyAll();
+ }
+
+ @Test
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replayAll();
+
+ try {
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+ verifyAll();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "\n Unexpected constructor call samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 4):"
+ + "\n samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 2): expected: 1, actual: 0",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replayAll();
+ try {
+ tested.makeDate();
+ verifyAll();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertTrue(e.getMessage().contains(MyClass.class.getName() + "(): expected: 1, actual: 0"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privateandfinal/PrivateFinalTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privateandfinal/PrivateFinalTest.java
new file mode 100644
index 0000000..8f395de
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privateandfinal/PrivateFinalTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.privateandfinal;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PrivateFinal.class)
+public class PrivateFinalTest {
+
+ @Test
+ public void testMockPrivatAndFinal() throws Exception {
+
+ PrivateFinal tested = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMultiplePartialMocksOfSameType() throws Exception {
+ PrivateFinal tested1 = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected1 = "Hello altered World";
+ expectPrivate(tested1, "sayIt", "name").andReturn(expected1);
+ replay(tested1);
+ PrivateFinal tested2 = createPartialMock(PrivateFinal.class,
+ "sayIt");
+ String expected2 = "Hello qweqweqwe";
+ expectPrivate(tested2, "sayIt", "name").andReturn(expected2);
+ replay(tested2);
+
+ String actual1 = tested1.say("name");
+ verify(tested1);
+ assertEquals("Expected and actual did not match", expected1, actual1);
+ String actual2 = tested2.say("name");
+ verify(tested2);
+ assertEquals("Expected and actual did not match", expected2, actual2);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/MockSelfPrivateFieldServiceClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/MockSelfPrivateFieldServiceClassTest.java
new file mode 100644
index 0000000..60b69fd
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/MockSelfPrivateFieldServiceClassTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.privatefield;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.Service;
+import samples.privatefield.MockSelfPrivateFieldServiceClass;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.reflect.Whitebox.setInternalState;
+
+/**
+ * A test class that demonstrate how to test classes that uses a private field
+ * for a service and has no corresponding setter and at the same time mocking a
+ * method of the actual test class. This is approach is common in DI frameworks
+ * like Guice and Wicket IoC.
+ *
+ * @author Johan Haleby
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MockSelfPrivateFieldServiceClass.class)
+public class MockSelfPrivateFieldServiceClassTest {
+
+ @Test
+ public void testGetCompositeMessage() throws Exception {
+ MockSelfPrivateFieldServiceClass tested = createPartialMock(MockSelfPrivateFieldServiceClass.class, "getOwnMessage");
+
+ Service serviceMock = createMock(Service.class);
+ setInternalState(tested, "service", serviceMock, MockSelfPrivateFieldServiceClass.class);
+
+ final String expected = "Hello world";
+ expectPrivate(tested, "getOwnMessage").andReturn("Hello");
+ expect(serviceMock.getServiceMessage()).andReturn(" world");
+
+ replay(serviceMock);
+ replay(tested);
+
+ final String actual = tested.getCompositeMessage();
+
+ verify(serviceMock);
+ verify(tested);
+
+ assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/SimplePrivateFieldServiceClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/SimplePrivateFieldServiceClassTest.java
new file mode 100644
index 0000000..f65d211
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatefield/SimplePrivateFieldServiceClassTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.privatefield;
+
+import org.junit.Test;
+import samples.Service;
+import samples.privatefield.SimplePrivateFieldServiceClass;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+import static org.powermock.reflect.Whitebox.setInternalState;
+
+/**
+ * A test class that demonstrate how to test class that uses a private field for
+ * a Service and has no corresponding setter. This is approach is common in DI
+ * frameworks like Guice and Wicket IoC.
+ *
+ * @author Johan Haleby
+ */
+public class SimplePrivateFieldServiceClassTest {
+
+ @Test
+ public void testSimplePrivateFieldServiceClass() throws Exception {
+ SimplePrivateFieldServiceClass tested = new SimplePrivateFieldServiceClass();
+ Service serviceMock = createMock(Service.class);
+ setInternalState(tested, "service", serviceMock, SimplePrivateFieldServiceClass.class);
+
+ final String expected = "Hello world!";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replay(serviceMock);
+ final String actual = tested.useService();
+
+ verify(serviceMock);
+
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testSimplePrivateFieldServiceClassTypeSafe() throws Exception {
+ SimplePrivateFieldServiceClass tested = new SimplePrivateFieldServiceClass();
+ Service serviceMock = createMock(Service.class);
+ setInternalState(tested, serviceMock);
+
+ final String expected = "Hello world!";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replay(serviceMock);
+ final String actual = tested.useService();
+
+ verify(serviceMock);
+
+ assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatemocking/PrivateMethodDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatemocking/PrivateMethodDemoTest.java
new file mode 100644
index 0000000..c3bd1db
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/privatemocking/PrivateMethodDemoTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.privatemocking;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.privatemocking.PrivateMethodDemo;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate private method mocking.
+ *
+ * @author Johan Haleby
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PrivateMethodDemo.class)
+public class PrivateMethodDemoTest {
+
+ @Test
+ public void testMockPrivateMethod() throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "sayIt", String.class);
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMockPrivateMethod_withArgument() throws Exception {
+ PrivateMethodDemo tested = new PrivateMethodDemo();
+ String expected = "Hello altered World";
+
+ String actual = (String) Whitebox.invokeMethod(tested, "sayIt",
+ "altered World");
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokePrivateMethod() throws Exception {
+
+ PrivateMethodDemo tested = new PrivateMethodDemo();
+ String expected = "Hello world";
+
+ String actual = (String) Whitebox.invokeMethod(tested, "sayIt");
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMethodCallingPrimitiveTestMethod() throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "aTestMethod", int.class);
+
+ final int expected = 42;
+ expectPrivate(tested, "aTestMethod", new Class<?>[] { int.class }, 10)
+ .andReturn(expected);
+
+ replay(tested);
+
+ final int actual = tested.methodCallingPrimitiveTestMethod();
+
+ verify(tested);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMethodCallingWrappedTestMethod() throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "aTestMethod", Integer.class);
+
+ final int expected = 42;
+ expectPrivate(tested, "aTestMethod", new Class<?>[] { Integer.class },
+ new Integer(15)).andReturn(expected);
+
+ replay(tested);
+
+ final int actual = tested.methodCallingWrappedTestMethod();
+
+ verify(tested);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMethodCallingWrappedTestMethod_reflectiveMethodLookup()
+ throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "aTestMethod", Integer.class);
+
+ final Method methodToExpect = PrivateMethodDemo.class
+ .getDeclaredMethod("aTestMethod", Integer.class);
+
+ final int expected = 42;
+ expectPrivate(tested, methodToExpect, 15).andReturn(expected);
+
+ replay(tested);
+
+ final int actual = tested.methodCallingWrappedTestMethod();
+
+ verify(tested);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testExpectPrivateWithArrayMatcher() throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "doArrayInternal");
+
+ expectPrivate(tested, "doArrayInternal", EasyMock
+ .aryEq((Object[]) new String[] { "hello" }));
+
+ replay(tested);
+
+ tested.doArrayStuff("hello");
+
+ verify(tested);
+ }
+
+ @Test
+ public void testExpectPrivateWithObjectMatcher() throws Exception {
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "doObjectInternal");
+
+ expectPrivate(tested, "doObjectInternal", EasyMock
+ .isA(CharSequence.class));
+
+ replay(tested);
+
+ tested.doObjectStuff("hello");
+
+ verify(tested);
+ }
+
+ @Test
+ public void testExpectPrivateMethodWithVarArgsParameters() throws Exception {
+ final String methodToExpect = "varArgsMethod";
+ final int expected = 7;
+ final int valueA = 2;
+ final int valueB = 3;
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ methodToExpect);
+
+ expectPrivate(tested, methodToExpect, valueA, valueB).andReturn(
+ expected);
+
+ replay(tested);
+
+ assertEquals(expected, tested.invokeVarArgsMethod(valueA, valueB));
+
+ verify(tested);
+ }
+
+ @Test
+ public void testExpectPrivateMethodWithoutSpecifyingMethodName_firstArgumentIsOfStringType()
+ throws Exception {
+ final String expected = "Hello world";
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "sayIt");
+
+ expectPrivate(tested, (String) null, "firstName", " ", "lastName")
+ .andReturn(expected);
+
+ replay(tested);
+
+ assertEquals(expected, tested.enhancedSay("firstName", "lastName"));
+
+ verify(tested);
+ }
+
+ @Test
+ public void testExpectPrivateMethodWithoutSpecifyingMethodName()
+ throws Exception {
+ final String expected = "Hello world";
+ PrivateMethodDemo tested = createPartialMock(PrivateMethodDemo.class,
+ "doSayYear");
+
+ expectPrivate(tested, 22, "name").andReturn(expected);
+
+ replay(tested);
+
+ assertEquals(expected, tested.sayYear("name", 22));
+
+ verify(tested);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/reflection/ReflectionInstantiatorTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/reflection/ReflectionInstantiatorTest.java
new file mode 100644
index 0000000..1eb0d56
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/reflection/ReflectionInstantiatorTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.reflection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.reflection.ReflectionInstantiator;
+import samples.reflection.UseMe;
+
+import static org.junit.Assert.assertTrue;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { UseMe.class })
+public class ReflectionInstantiatorTest {
+
+ @Test
+ public void whenClassIsInstantiatedUsingReflectionMakeSureItCanBeCastedToPowerMockLoadedVersionOfTheClass()
+ throws Exception {
+ ReflectionInstantiator reflectionInstantiator = new ReflectionInstantiator();
+ assertTrue(
+ "Reflection instantiation doesn't work, Thread context class-loader not set to MockCL",
+ reflectionInstantiator.instantiateUseMe());
+ }
+
+ @Test
+ @PrepareForTest(UseMe.class)
+ public void whenClassIsInstantiatedUsingReflectionMakeSureItCanBeCastedToPowerMockLoadedVersionOfTheClassWhenUsingChunking()
+ throws Exception {
+ ReflectionInstantiator reflectionInstantiator = new ReflectionInstantiator();
+ assertTrue(
+ "Reflection instantiation doesn't work, Thread context class-loader not set to MockCL",
+ reflectionInstantiator.instantiateUseMe());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForExpectNewTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForExpectNewTest.java
new file mode 100644
index 0000000..3711820
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForExpectNewTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.replayall;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.newmocking.MyClass;
+
+import java.io.IOException;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * The purpose of this test is to try-out the replay all functionality in
+ * PowerMock in combination with expectNew.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class })
+public class ReplayAllForExpectNewTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replayAll();
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyAll();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replayAll();
+
+ String actual = tested.getMessage();
+
+ verifyAll();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testReplayAllWithExpectNewWhenTheClassBeingConstructedIsNotPreparedForTest() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replayAll();
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyAll();
+ }
+
+ @Test
+ public void testReplayAllWithAdditionalMocks() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = EasyMock.createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replayAll(expectNewServiceImplMock);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyAll();
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForStaticMethodsTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForStaticMethodsTest.java
new file mode 100644
index 0000000..9a272af
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/replayall/ReplayAllForStaticMethodsTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.replayall;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * The purpose of this test is to try-out the replay all functionality in
+ * PowerMock in combination with static and instance mocking.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class ReplayAllForStaticMethodsTest {
+
+ @Test
+ public void testMockStaticMethodAndInstanceMethod() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class, "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replayAll();
+
+ String actual = tested.getMessage();
+
+ verifyAll();
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetForStaticMethodsTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetForStaticMethodsTest.java
new file mode 100644
index 0000000..013b0e4
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetForStaticMethodsTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.resetmock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticService;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Asserts that it works to reset mocks for static methods even after verify has
+ * been invoked.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticService.class)
+public class ResetForStaticMethodsTest {
+
+ @Test
+ public void assertThatResetWorksForStaticMethods() throws InterruptedException {
+ mockStatic(StaticService.class);
+
+ StaticService.sayHello();
+ expectLastCall().once();
+
+ replay(StaticService.class);
+
+ StaticService.sayHello();
+
+ verify(StaticService.class);
+
+ reset(StaticService.class);
+
+ StaticService.sayHello();
+ expectLastCall().once();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetMockTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetMockTest.java
new file mode 100644
index 0000000..82e22ca
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/resetmock/ResetMockTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.resetmock;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+import samples.newmocking.MyClass;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Tests to verify that the reset functionality works.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExpectNewDemo.class)
+public class ResetMockTest {
+
+ @Test
+ public void assertManualResetWorks() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ String message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+
+ reset(myClassMock);
+ reset(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+ }
+
+ @Test
+ public void assertManualResetWorksWhenMixingInstanceAndClassMocks() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ String message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+
+ reset(myClassMock, MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+ }
+
+ @Test
+ public void assertResetAllWorks() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ String message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+
+ resetAll();
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+ expect(myClassMock.getMessage()).andReturn("message");
+
+ replayAll();
+
+ message = tested.getMessage();
+
+ verifyAll();
+ assertEquals("message", message);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/servletmocking/SampleServletTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/servletmocking/SampleServletTest.java
new file mode 100644
index 0000000..9fa4b2d
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/servletmocking/SampleServletTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.servletmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.servletmocking.SampleServlet;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SampleServlet.class)
+public class SampleServletTest {
+
+ @Test
+ public void doGet() throws Exception {
+ SampleServlet servlet = new SampleServlet();
+
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ PrintWriter writer = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(writer);
+ writer.write("out");
+
+ replay(response, writer);
+
+ servlet.doGet(null, response);
+
+ verify(response, writer);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/simplereturn/SimpleReturnExampleUserTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/simplereturn/SimpleReturnExampleUserTest.java
new file mode 100644
index 0000000..3a6a8b0
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/simplereturn/SimpleReturnExampleUserTest.java
@@ -0,0 +1,30 @@
+package samples.junit4.simplereturn;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.simplereturn.SimpleReturnExample;
+import samples.simplereturn.SimpleReturnExampleUser;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleReturnExample.class)
+public class SimpleReturnExampleUserTest {
+
+ @Test
+ public void testCreateMockDelegatedToEasyMock() throws Exception {
+ SimpleReturnExample mock = createMock(SimpleReturnExample.class);
+ expect(mock.mySimpleMethod()).andReturn(2);
+
+ replay(mock);
+
+ assertEquals(2, new SimpleReturnExampleUser(mock).myMethod());
+
+ verify(mock);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/LogicAndTestInSameClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/LogicAndTestInSameClassTest.java
new file mode 100644
index 0000000..9f5780e
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/LogicAndTestInSameClassTest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit4.singleton;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * A simple test that asserts that it's possible execute a test from the same
+ * class that defines the logic to test.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, LogicAndTestInSameClassTest.class })
+public class LogicAndTestInSameClassTest {
+
+ private static String invokeMethod() {
+ return StaticService.say("hello");
+ }
+
+ @Test
+ public void assertThatTestAndInstanceCanBeInSameClass() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replayAll();
+ assertEquals(expected, LogicAndTestInSameClassTest.invokeMethod());
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticNotPreparedTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticNotPreparedTest.java
new file mode 100644
index 0000000..c7dfb92
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticNotPreparedTest.java
@@ -0,0 +1,31 @@
+package samples.junit4.singleton;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replay;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+public class MockStaticNotPreparedTest {
+
+ @Ignore("Easymock uses static methods and cglib, so call cannot be intercept and exception cannot be changes, " +
+ "util ByteBuddy is not used.")
+ @Test
+ public void testWhenNotPrepared() throws Exception {
+
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ expect(StaticService.say(argument)).andReturn(expected);
+ replay(StaticService.class);
+
+
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticTest.java
new file mode 100644
index 0000000..1e0cc5c
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/MockStaticTest.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.singleton;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.sayFinal("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call StaticService.sayFinal(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMockStaticNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testMockStaticFinalNative() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinalNative("hello");
+
+ verify(StaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void mockAStaticMethod() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "qwe";
+ expect(StaticService.doStatic(5)).andReturn(expected);
+ replay(StaticService.class);
+
+ String actual = StaticService.doStatic(5);
+ assertEquals(expected, actual);
+ verify(StaticService.class);
+ }
+
+ @Test
+ public void mockMockStatic_times2() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloHelper();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHello();
+
+ verify(StaticHelper.class);
+ }
+
+ @Test
+ public void mockStaticCallingOtherStatic() throws Exception {
+ mockStatic(StaticHelper.class);
+ StaticHelper.sayHelloAgain();
+ expectLastCall().times(2);
+ replay(StaticHelper.class);
+
+ StaticService.sayHelloAgain();
+
+ verify(StaticHelper.class);
+ }
+
+ @Test
+ public void testMockPrivateStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testMockPrivateFinalStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateFinalStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateFinalStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateFinalStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testMockPrivateNativeFinalStatic() throws Exception {
+ mockStaticPartial(StaticService.class, "sayPrivateNativeFinalStatic", String.class);
+
+ final String expected = "Hello world";
+ expectPrivate(StaticService.class, "sayPrivateNativeFinalStatic", "name").andReturn(expected);
+
+ replay(StaticService.class);
+
+ String actual = (String) Whitebox.invokeMethod(StaticService.class, "sayPrivateNativeFinalStatic", "name");
+
+ verify(StaticService.class);
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void innerClassesWork() {
+ assertEquals(17, StaticService.getNumberFromInner());
+ }
+
+ @Test
+ public void innerInstanceClassesWork() {
+ assertEquals(23, StaticService.getNumberFromInnerInstance());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/SimpleStaticServiceTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/SimpleStaticServiceTest.java
new file mode 100644
index 0000000..0bd018e
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/singleton/SimpleStaticServiceTest.java
@@ -0,0 +1,41 @@
+package samples.junit4.singleton;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.SimpleStaticService;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleStaticService.class)
+public class SimpleStaticServiceTest {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(SimpleStaticService.class);
+ final String expected = "Hello altered World";
+
+ expect(SimpleStaticService.say("hello")).andReturn("Hello altered World");
+ replay(SimpleStaticService.class);
+
+ final String actual = SimpleStaticService.say("hello");
+
+ verify(SimpleStaticService.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ SimpleStaticService.say("world");
+ fail("Should throw AssertionError!");
+ } catch (final AssertionError e) {
+ assertEquals("\n Unexpected method call SimpleStaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/EvilHashCode.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/EvilHashCode.java
new file mode 100644
index 0000000..62f608f
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/EvilHashCode.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.stackoverflow;
+
+public class EvilHashCode {
+ //Required to produce error
+ public String s = returnS();
+
+ public String returnS()
+ {
+ return "s";
+ }
+
+ @Override
+ public int hashCode() {
+ return evilHashCode();
+ }
+
+ public int evilHashCode() {
+ return 3;
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/StackOverFlowTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/StackOverFlowTest.java
new file mode 100644
index 0000000..27d96e1
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stackoverflow/StackOverFlowTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.stackoverflow;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Make sure we don't get a stackOverFlowError here. Thanks to ride.sputnik for
+ * reporting this!
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(EvilHashCode.class)
+public class StackOverFlowTest {
+
+ @Test
+ public void testStackOverFlowShouldNotOccur() throws Exception {
+ new EvilHashCode();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceDemoTest.java
new file mode 100644
index 0000000..9a68090
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceDemoTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticandinstance;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class StaticAndInstanceDemoTest {
+
+ @Test
+ public void testMockStaticMethodAndInstanceMethod() throws Exception {
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class,
+ "getPrivateMessage");
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(
+ staticExpected);
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+
+ @Test
+ public void testMockPrivateButNotStatic() throws Exception {
+ StaticAndInstanceDemo tested = createPartialMock(StaticAndInstanceDemo.class,
+ "getPrivateMessage");
+
+ final String privateExpected = "A private message ";
+ expectPrivate(tested, "getPrivateMessage").andReturn(privateExpected);
+
+ replay(tested);
+
+ String actual = tested.getMessage();
+
+ verify(tested);
+
+ assertEquals(privateExpected + "hello world!", actual);
+ }
+
+ @Test
+ public void testMockStaticButNotInstance() throws Exception {
+ StaticAndInstanceDemo tested = new StaticAndInstanceDemo();
+
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ final String staticExpected = "static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(
+ staticExpected);
+
+ replay(StaticAndInstanceDemo.class);
+
+ String actual = tested.getMessage();
+
+ verify(StaticAndInstanceDemo.class);
+
+ assertEquals("Private " + staticExpected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceWithConstructorCodeDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceWithConstructorCodeDemoTest.java
new file mode 100644
index 0000000..5706e69
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticandinstance/StaticAndInstanceWithConstructorCodeDemoTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticandinstance;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+import samples.staticandinstance.StaticAndInstanceWithConstructorCodeDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * The purpose of this test class is to verify that the
+ * http://code.google.com/p/powermock/issues/detail?id=4 is fixed.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class StaticAndInstanceWithConstructorCodeDemoTest {
+
+ @Test
+ public void testStaticAndInstanceWithConstructor() throws Exception {
+ StaticAndInstanceDemo staticAndInstanceDemoMock = createMock(StaticAndInstanceDemo.class);
+
+ StaticAndInstanceWithConstructorCodeDemo tested = new StaticAndInstanceWithConstructorCodeDemo(
+ staticAndInstanceDemoMock);
+
+ niceReplayAndVerify();
+
+ mockStaticPartial(StaticAndInstanceDemo.class, "getStaticMessage");
+
+ final String instanceExpected = "value";
+ expect(staticAndInstanceDemoMock.getMessage()).andReturn(
+ instanceExpected);
+
+ final String staticExpected = "a static message";
+ expect(StaticAndInstanceDemo.getStaticMessage()).andReturn(
+ staticExpected);
+
+ replay(StaticAndInstanceDemo.class, staticAndInstanceDemoMock, tested);
+
+ String actual = tested.getMessage();
+
+ verify(StaticAndInstanceDemo.class, staticAndInstanceDemoMock, tested);
+
+ assertEquals(staticExpected + instanceExpected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/AbstractStaticInitializerTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/AbstractStaticInitializerTest.java
new file mode 100644
index 0000000..09e74d7
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/AbstractStaticInitializerTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticinitializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticinitializer.AbstractStaticInitializerExample;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("samples.staticinitializer.AbstractStaticInitializerExample")
+public class AbstractStaticInitializerTest {
+
+ @Test
+ public void suppressStaticInitializerInAbstractClass() throws Exception {
+ assertEquals("something", AbstractStaticInitializerExample.getStaticString());
+ }
+
+ @Test
+ public void suppressStaticInitializerInAbstractClassWhenInstantiated() throws Exception {
+ AbstractStaticInitializerExample tested = new AbstractStaticInitializerExample() {};
+ assertEquals("something", tested.getString());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/EvilStaticInitializerExampleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/EvilStaticInitializerExampleTest.java
new file mode 100644
index 0000000..56f5c86
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/EvilStaticInitializerExampleTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticinitializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticinitializer.EvilStaticInitializerExample;
+
+import static org.hamcrest.core.IsInstanceOf.instanceOf;
+import static org.junit.Assert.*;
+
+/**
+ * Test that demonstrates a (naive) example of when chunking may be handy.
+ */
+ at RunWith(PowerMockRunner.class)
+public class EvilStaticInitializerExampleTest {
+
+ @Test
+ @SuppressStaticInitializationFor("samples.staticinitializer.EvilStaticInitializerExample")
+ public void assertNativeCodeInvocationWorks() throws Exception {
+ EvilStaticInitializerExample tested = new EvilStaticInitializerExample();
+ assertThat(tested.doSomeNativeStuffUsingTheLoadedSystemLibrary(), instanceOf(String.class));
+ }
+
+ @Test
+ public void assertCorrectErrorMessageIfLibraryNotFound() throws Exception {
+ try {
+ new EvilStaticInitializerExample();
+ fail("Should throw unsatisfied link error!");
+ } catch (UnsatisfiedLinkError error) {
+ assertEquals(error.getMessage(), EvilStaticInitializerExample.FAILED_TO_LOAD_LIBRARY_MESSAGE);
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/InterfaceStaticInitializerExampleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/InterfaceStaticInitializerExampleTest.java
new file mode 100644
index 0000000..086a3e4
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/InterfaceStaticInitializerExampleTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticinitializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticinitializer.InterfaceComputation;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor( { "samples.staticinitializer.InterfaceA", "samples.staticinitializer.InterfaceB",
+ "samples.staticinitializer.InterfaceC" })
+public class InterfaceStaticInitializerExampleTest {
+
+ @Test
+ public void testSupressStaticInitializer() throws Exception {
+ assertEquals(0, InterfaceComputation.calculateWithinHierarchy());
+ }
+
+ @Test
+ public void testSupressStaticInitializer2() throws Exception {
+ assertEquals(0, InterfaceComputation.calculateWithReference());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/StaticInitializerExampleTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/StaticInitializerExampleTest.java
new file mode 100644
index 0000000..68e89ac
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/staticinitializer/StaticInitializerExampleTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.staticinitializer;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.staticinitializer.StaticInitializerExample;
+
+import java.util.HashSet;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+ at RunWith(PowerMockRunner.class)
+ at SuppressStaticInitializationFor("samples.staticinitializer.StaticInitializerExample")
+public class StaticInitializerExampleTest {
+
+ @Test
+ public void testSupressStaticInitializerAndSetFinalField() throws Exception {
+ assertNull("Should be null because the static initializer should be suppressed", StaticInitializerExample.getMySet());
+ final HashSet<String> hashSet = new HashSet<String>();
+ Whitebox.setInternalState(StaticInitializerExample.class, "mySet", hashSet);
+ assertSame(hashSet, Whitebox.getInternalState(StaticInitializerExample.class, "mySet"));
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/strict/StrictDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/strict/StrictDemoTest.java
new file mode 100644
index 0000000..090ff4a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/strict/StrictDemoTest.java
@@ -0,0 +1,58 @@
+package samples.junit4.strict;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.strict.StrictDemo;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This is a simple test case for the {@link StrictDemo} class that demonstrates
+ * that strict method mocking works.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StrictDemo.class)
+public class StrictDemoTest {
+
+ @Test
+ public void testCallB_notStrict() throws Exception {
+ StrictDemo tested = createPartialMock(StrictDemo.class, "A", "B");
+ expectPrivate(tested, "B").times(1);
+ expectPrivate(tested, "A").times(1);
+
+ replay(tested);
+
+ tested.callAThenB();
+
+ verify(tested);
+ }
+
+ @Test(expected = AssertionError.class)
+ public void testCallB_strict_failure() throws Exception {
+ StrictDemo tested = createStrictPartialMock(StrictDemo.class, "A", "B");
+ expectPrivate(tested, "B").times(1);
+ expectPrivate(tested, "A").times(1);
+
+ replay(tested);
+
+ tested.callAThenB();
+
+ verify(tested);
+ }
+
+ @Test
+ public void testCallB_strict_ok() throws Exception {
+ StrictDemo tested = createStrictPartialMock(StrictDemo.class, "A", "B");
+ expectPrivate(tested, "A").times(1);
+ expectPrivate(tested, "B").times(1);
+
+ replay(tested);
+
+ tested.callAThenB();
+
+ verify(tested);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stubmethod/StubMethodTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stubmethod/StubMethodTest.java
new file mode 100644
index 0000000..86f5461
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/stubmethod/StubMethodTest.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.stubmethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+import samples.suppressmethod.SuppressMethod;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SuppressMethod.class)
+public class StubMethodTest {
+
+ @Test
+ public void whenStubbingInstanceMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expectedValue = "Hello";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expectedValue);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expectedValue, tested.getObject());
+ assertEquals(expectedValue, tested.getObject());
+ }
+
+ @Test
+ public void whenStubbingStaticMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expectedValue = "Hello";
+ stub(method(SuppressMethod.class, "getObjectStatic")).toReturn(expectedValue);
+
+ assertEquals(expectedValue, SuppressMethod.getObjectStatic());
+ assertEquals(expectedValue, SuppressMethod.getObjectStatic());
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodWithPrimiteValueTheMethodReturnsTheStubbedValue() throws Exception {
+ float expectedValue = 4;
+ stub(method(SuppressMethod.class, "getFloat")).toReturn(expectedValue);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expectedValue, tested.getFloat(), 0.0f);
+ assertEquals(expectedValue, tested.getFloat(), 0.0f);
+ }
+
+ @Test(expected = TooManyMethodsFoundException.class)
+ public void whenSeveralMethodsFoundThenTooManyMethodsFoundExceptionIsThrown() throws Exception {
+ stub(method(SuppressMethod.class, "sameName"));
+ }
+
+ @Test(expected = MethodNotFoundException.class)
+ public void whenNoMethodsFoundThenMethodNotFoundExceptionIsThrown() throws Exception {
+ stub(method(SuppressMethod.class, "notFound"));
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodByPassingTheMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expected = "Hello";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expected);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expected, tested.getObject());
+ assertEquals(expected, tested.getObject());
+ }
+
+ @Test
+ public void whenStubbingStaticMethodByPassingTheMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expected = "Hello";
+ stub(method(SuppressMethod.class, "getObjectStatic")).toReturn(expected);
+
+ assertEquals(expected, SuppressMethod.getObjectStatic());
+ assertEquals(expected, SuppressMethod.getObjectStatic());
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void whenStubbingInstanceMethodWithWrongReturnTypeThenClasscastExceptionIsThrown() throws Exception {
+ String illegalReturnType = "Hello";
+ stub(method(SuppressMethod.class, "getFloat")).toReturn(illegalReturnType);
+ SuppressMethod tested = new SuppressMethod();
+ tested.getFloat();
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodToThrowExceptionTheMethodThrowsTheStubbedException() throws Exception {
+ Exception expected = new Exception("message");
+ stub(method(SuppressMethod.class, "getObject")).toThrow(expected);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ try {
+ tested.getObject();
+ fail();
+ } catch (Exception e) {
+ assertEquals("message", e.getMessage());
+ }
+ }
+
+ @Test
+ public void whenStubbingStaticMethodToThrowExceptionTheMethodThrowsTheStubbedException() throws Exception {
+ Exception expected = new Exception("message");
+ stub(method(SuppressMethod.class, "getObjectStatic")).toThrow(expected);
+ try {
+ SuppressMethod.getObjectStatic();
+ fail();
+ } catch (Exception e) {
+ assertEquals("message", e.getMessage());
+ }
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/CreateUnmockedTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/CreateUnmockedTest.java
new file mode 100644
index 0000000..1ac5959
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/CreateUnmockedTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.suppressconstructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.suppressconstructor.SuppressConstructorDemo;
+import samples.suppressconstructor.SuppressSpecificConstructorDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+ at RunWith(PowerMockRunner.class)
+public class CreateUnmockedTest {
+
+ @Test
+ public void testUnmockedWithNoConstructorAndReplayVerify() throws Exception {
+ SuppressSpecificConstructorDemo object = Whitebox.newInstance(SuppressSpecificConstructorDemo.class);
+ PowerMock.niceReplayAndVerify();
+ PowerMock.replay(object);
+
+ assertEquals("Hello", object.getHello());
+
+ PowerMock.verify(object);
+ }
+
+ @Test
+ public void testUnmockedWithConstructorAndAllowReplay() throws Exception {
+ PowerMock.niceReplayAndVerify();
+ SuppressConstructorDemo object = new SuppressConstructorDemo("Hello");
+ PowerMock.replay(object);
+
+ assertEquals("Hello", object.getMessage());
+
+ PowerMock.verify(object);
+ }
+
+ @Test
+ public void testUnmockedWithReplayCausesException() throws Exception {
+ SuppressConstructorDemo object = new SuppressConstructorDemo("Hello");
+ try {
+ PowerMock.replay(object);
+ fail("Replay should only work on mocks");
+ } catch (RuntimeException e) {
+ // ignore
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorDemoTest.java
new file mode 100644
index 0000000..e8de2f6
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorDemoTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.suppressconstructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.suppressconstructor.SuppressConstructorDemo;
+import samples.suppressconstructor.SuppressConstructorSubclassDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * This test demonstrates how to tell PowerMock to avoid executing constructor
+ * code for a certain class. This is crucial in certain tests where the
+ * constructor or a subclass's constructor performs operations that are of no
+ * concern to the unit test of the actual class or if the constructor performs
+ * operations, such as getting services from a runtime environment that has not
+ * been initialized. In normal situations you're forced to create an integration
+ * or function test for the class instead (and thus the runtime environment is
+ * available). This is not particularly good when it comes to testing method
+ * logic. PowerMock solves these problems by letting you specify the
+ * {@link PowerMock#suppressConstructor(Class...)} method
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SuppressConstructorDemo.class)
+public class SuppressConstructorDemoTest {
+
+ /**
+ * This test makes sure that the real constructor has never been called.
+ */
+ @Test
+ public void testSuppressConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorDemo.class));
+ final SuppressConstructorDemo tested = new SuppressConstructorDemo("a message");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+
+ /**
+ * This test makes sure that the real parent constructor has never been
+ * called.
+ */
+ @Test
+ public void testSuppressParentConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorSubclassDemo.class));
+ final SuppressConstructorDemo tested = new SuppressConstructorDemo("a message");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+
+ /**
+ * This test makes sure that it's possible to also mock methods from the
+ * class under test at the same time as skipping constructor execution.
+ */
+ @Test
+ public void testPartialMockingAndSuppressParentConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorSubclassDemo.class));
+ final SuppressConstructorDemo tested = createPartialMock(SuppressConstructorDemo.class, "returnAMessage");
+ final String expected = "Hello world!";
+ expectPrivate(tested, "returnAMessage").andReturn(expected);
+ replay(tested);
+
+ final String actual = tested.getMyOwnMessage();
+
+ verify(tested);
+
+ assertEquals(expected, actual);
+
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorHierarchyDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
new file mode 100644
index 0000000..4e46ea5
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressConstructorHierarchyDemoTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.suppressconstructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.suppressconstructor.InvokeConstructor;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+
+import static org.junit.Assert.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at PrepareForTest(SuppressConstructorHierarchy.class)
+ at RunWith(PowerMockRunner.class)
+public class SuppressConstructorHierarchyDemoTest {
+
+ @Test
+ public void testSuppressConstructorHierarchy() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ final String message = new InvokeConstructor().doStuff("qwe");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code. Message was \"" + message + "\".",
+ message);
+ }
+
+ @Test
+ @PrepareForTest
+ public void testNotSuppressConstructorWithoutByteCodeManipulation() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNotSuppressConstructorWithByteCodeManipulation() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ /**
+ * This simple test demonstrate that it's possible to continue execution
+ * with the default <code>PrepareForTest</code> settings (i.e. using a
+ * byte-code manipulated version of the SuppressConstructorHierarchyDemo
+ * class).
+ */
+ @Test
+ public void testSuppressConstructorHierarchyAgain() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+ assertEquals(42, tested.getNumber());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressNonParentConstructorDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressNonParentConstructorDemoTest.java
new file mode 100644
index 0000000..c0b38ce
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressconstructor/SuppressNonParentConstructorDemoTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.suppressconstructor;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+import samples.suppressconstructor.SuppressNonParentConstructorDemo;
+
+import static org.junit.Assert.assertEquals;
+
+public class SuppressNonParentConstructorDemoTest {
+
+ @Test
+ public void testNewInstanceWithoutInvokingConstructor() throws Exception {
+ SuppressNonParentConstructorDemo constructorDemo = Whitebox
+ .newInstance(SuppressNonParentConstructorDemo.class);
+ assertEquals("Hello", constructorDemo.getHello());
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNewInstanceInvokingConstructor() throws Exception {
+ new SuppressNonParentConstructorDemo("failing");
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/ItemRepositoryTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/ItemRepositoryTest.java
new file mode 100644
index 0000000..6f22abe
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/ItemRepositoryTest.java
@@ -0,0 +1,26 @@
+package samples.junit4.suppressfield;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.suppressfield.ItemRepository;
+
+import static org.powermock.api.support.membermodification.MemberMatcher.field;
+import static org.powermock.api.support.membermodification.MemberMatcher.fields;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { ItemRepository.class })
+ at SuppressStaticInitializationFor("samples.suppressfield.ItemRepository")
+public class ItemRepositoryTest {
+ @Test(expected = NullPointerException.class)
+ public void testaddItem() throws Exception {
+ suppress(fields(field(ItemRepository.class, "itemMap"), field(ItemRepository.class, "totalItems")));
+
+ ItemRepository objRep = Whitebox.newInstance(ItemRepository.class);
+ objRep.addItem("key", "value");
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/SuppressFieldTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/SuppressFieldTest.java
new file mode 100644
index 0000000..497d3c3
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressfield/SuppressFieldTest.java
@@ -0,0 +1,98 @@
+package samples.junit4.suppressfield;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.suppressfield.SuppressField;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.support.membermodification.MemberMatcher.field;
+import static org.powermock.api.support.membermodification.MemberMatcher.fields;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * Unit tests that asserts that field suppression works.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SuppressField.class)
+public class SuppressFieldTest {
+
+ @Test
+ public void assertThatSpecificStaticFinalFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "MY_OBJECT"));
+ assertNull(SuppressField.getMyObject());
+ }
+
+ @Ignore("Final primitive types doesn't work, see issue at https://github.com/jayway/powermock/issues/105")
+ @Test
+ public void assertThatSpecificStaticFinalPrimitiveFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "MY_VALUE"));
+ assertEquals(0, SuppressField.getMyValue());
+ }
+
+ @Ignore("Final primitive types doesn't work, see issue at https://github.com/jayway/powermock/issues/105")
+ @Test
+ public void assertThatSpecificInstanceFinalPrimitiveFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "myBoolean"));
+ SuppressField suppressField = new SuppressField();
+ assertEquals(false, suppressField.isMyBoolean());
+ }
+
+ @Test
+ public void assertThatSpecificInstanceFinalFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "myWrappedBoolean"));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getMyWrappedBoolean());
+ }
+
+ @Test
+ public void assertThatSpecificPrimitiveInstanceFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "myChar"));
+ SuppressField suppressField = new SuppressField();
+ assertEquals(' ', suppressField.getMyChar());
+ }
+
+ @Test
+ public void assertThatSpecificInstanceFieldSuppressionWorks() throws Exception {
+ suppress(field(SuppressField.class, "mySecondValue"));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getMySecondValue());
+ }
+
+ @Test
+ public void assertThatSpecificInstanceFieldSuppressionWhenSpecifingClassAndFieldNameWorks() throws Exception {
+ suppress(field(SuppressField.class, "mySecondValue"));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getMySecondValue());
+ }
+
+ @Test
+ public void assertThatMultipleInstanceFieldSuppressionWorks() throws Exception {
+ suppress(fields(SuppressField.class, "mySecondValue", "myChar"));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getMySecondValue());
+ assertEquals(' ', suppressField.getMyChar());
+ assertEquals(Boolean.TRUE, suppressField.getMyWrappedBoolean());
+ }
+
+ // TODO Add final tests here as well when they work
+ @Test
+ public void assertThatAllFieldSuppressionWorks() throws Exception {
+ suppress(fields(SuppressField.class));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getMySecondValue());
+ assertEquals(' ', suppressField.getMyChar());
+ assertNull(suppressField.getMyWrappedBoolean());
+ assertNull(SuppressField.getMyObject());
+ }
+
+ @Test
+ public void assertThatObjectIsNeverInstansiated() throws Exception {
+ suppress(field(SuppressField.class, "domainObject"));
+ SuppressField suppressField = new SuppressField();
+ assertNull(suppressField.getDomainObject());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressmethod/SuppressMethodTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressmethod/SuppressMethodTest.java
new file mode 100644
index 0000000..6c5729a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/suppressmethod/SuppressMethodTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.suppressmethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticExample;
+import samples.suppressmethod.SuppressMethod;
+import samples.suppressmethod.SuppressMethodExample;
+import samples.suppressmethod.SuppressMethodParent;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberMatcher.methods;
+import static org.powermock.api.support.membermodification.MemberMatcher.methodsDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { SuppressMethod.class, SuppressMethodExample.class, StaticExample.class })
+public class SuppressMethodTest {
+
+ @Test
+ public void testGetObject() throws Exception {
+ suppress(method(SuppressMethod.class, "getObject"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertNull("A method returning Object should return null after suppressing method code.", tested.getObject());
+ }
+
+ @Test
+ public void testSuppressMultipleMethods() throws Exception {
+ suppress(methods(SuppressMethod.class, "getObject", "getShort"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertNull("A method returning Object should return null after suppressing method code.", tested.getObject());
+ assertEquals("A method returning a short should return 0 after suppressing method code.", 0, tested.getShort());
+ }
+
+ @Test
+ public void testGetObjectStatic() throws Exception {
+ suppress(method(SuppressMethod.class, "getObjectStatic"));
+
+ assertNull("A method returning Object should return null after suppressing method code.", SuppressMethod
+ .getObjectStatic());
+ }
+
+ @Test
+ public void testGetByte() throws Exception {
+ suppress(method(SuppressMethod.class, "getByte"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a byte should return 0 after suppressing method code.", 0, tested.getByte());
+ }
+
+ @Test
+ public void testGetShort() throws Exception {
+ suppress(method(SuppressMethod.class, "getShort"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a short should return 0 after suppressing method code.", 0, tested.getShort());
+ }
+
+ @Test
+ public void testGetInt() throws Exception {
+ suppress(method(SuppressMethod.class, "getInt"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning an int should return 0 after suppressing method code.", 0, tested.getInt());
+ }
+
+ @Test
+ public void testGetLong() throws Exception {
+ suppress(method(SuppressMethod.class, "getLong"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a long should return 0 after suppressing method code.", 0, tested.getLong());
+ }
+
+ @Test
+ public void testGetBoolean() throws Exception {
+ suppress(method(SuppressMethod.class, "getBoolean"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertFalse("A method returning a boolean should return false after suppressing method code.", tested
+ .getBoolean());
+ }
+
+ @Test
+ public void testGetFloat() throws Exception {
+ suppress(method(SuppressMethod.class, "getFloat"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a float should return 0.0f after suppressing method code.", 0.0f, tested
+ .getFloat(), 0);
+ }
+
+ @Test
+ public void testGetDouble() throws Exception {
+ suppress(method(SuppressMethod.class, "getDouble"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a double should return 0.0d after suppressing method code.", 0.0d, tested
+ .getDouble(), 0);
+ }
+
+ @Test
+ public void testGetDouble_parameter() throws Exception {
+ suppress(method(SuppressMethod.class, "getDouble", new Class<?>[] { double.class }));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("A method returning a double should return 0.0d after suppressing method code.", 0.0d, tested
+ .getDouble(8.7d), 0);
+ }
+
+ @Test
+ public void testInvokeVoid() throws Exception {
+ suppress(method(SuppressMethod.class, "invokeVoid", new Class<?>[] { StringBuilder.class }));
+
+ SuppressMethod tested = new SuppressMethod();
+ // Should not cause an NPE when suppressing code.
+ tested.invokeVoid(null);
+ }
+
+ @Test
+ public void testInvokeVoid_noParameterTypeSupplied() throws Exception {
+ suppress(method(SuppressMethod.class, "invokeVoid"));
+
+ SuppressMethod tested = new SuppressMethod();
+ // Should not cause an NPE when suppressing code.
+ tested.invokeVoid(null);
+ }
+
+ @Test
+ public void suppressAllMethodsInMultipleClasses() throws Exception {
+ suppress(methodsDeclaredIn(SuppressMethod.class, SuppressMethodExample.class));
+
+ SuppressMethod tested1 = new SuppressMethod();
+ SuppressMethodExample tested2 = new SuppressMethodExample();
+ // Should not cause an NPE when suppressing code.
+ tested1.invokeVoid(null);
+
+ assertNull(tested1.getObject());
+ assertEquals(0, tested1.getInt());
+ assertNull(tested2.getObject());
+ }
+
+ @Test
+ public void suppressPublicStaticMethod() throws Exception {
+ suppress(method(StaticExample.class, "staticVoidMethod"));
+
+ StaticExample.staticVoidMethod();
+ }
+
+ @Test
+ public void suppressOverridingMethod() throws Exception {
+ suppress(method(SuppressMethod.class, "myMethod"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals(0, tested.myMethod());
+ }
+
+ @Test
+ public void testSuppressMethodInParentOnly() throws Exception {
+ suppress(method(SuppressMethodParent.class, "myMethod"));
+
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals(20, tested.myMethod());
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/swing/ReallySimpleSwingDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/swing/ReallySimpleSwingDemoTest.java
new file mode 100644
index 0000000..1689843
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/swing/ReallySimpleSwingDemoTest.java
@@ -0,0 +1,39 @@
+package samples.junit4.swing;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.swing.ReallySimpleSwingDemo;
+
+import javax.swing.*;
+
+import static org.junit.Assume.assumeTrue;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Unit test that makes sure that PowerMock works with Swing components.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(JOptionPane.class)
+public class ReallySimpleSwingDemoTest {
+
+ @Test
+ public void assertThatPowerMockWorksWithSwingComponents() throws Exception {
+ // Currently this tests fails on Java 8, see issue 504.
+ assumeTrue(Float.valueOf(System.getProperty("java.specification.version")) < 1.8f);
+
+ final String message = "powermock";
+
+ mockStatic(JOptionPane.class);
+
+ JOptionPane.showMessageDialog(null, message);
+ expectLastCall().once();
+
+ replayAll();
+
+ new ReallySimpleSwingDemo().displayMessage(message);
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/FieldMockDefect.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/FieldMockDefect.java
new file mode 100644
index 0000000..5d33220
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/FieldMockDefect.java
@@ -0,0 +1,44 @@
+package samples.junit4.system;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.lang.reflect.Field;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ *
+ * The reason why it fails is because we create a new instance of the field
+ * using Whitebox but then hashCode doesn't work because it's missing
+ * constructor args.
+ * <p>
+ *
+ * if (Field.class.isAssignableFrom(mock.getClass())) {
+ * Whitebox.setInternalState(mock, "clazz", (Object) Object.class);
+ * Whitebox.setInternalState(mock, "name", Object.class.getName()); }
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(Field.class)
+public class FieldMockDefect {
+ @Test
+ public void test() {
+ final Field fieldMock = createMock(Field.class);
+ expect(fieldMock.getName()).andReturn("foo");
+ replayAll();
+ assertEquals("foo", new ClassUnderTest().foo(fieldMock));
+ verifyAll();
+
+ }
+
+ private static final class ClassUnderTest {
+ public String foo(Field field) {
+ return field.getName();
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/SystemClassUserTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/SystemClassUserTest.java
new file mode 100644
index 0000000..cda32cf
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/system/SystemClassUserTest.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.system;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.system.SystemClassUser;
+
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Demonstrates PowerMock's ability to mock non-final and final system classes.
+ * To mock a system class you need to prepare the calling class for testing.
+ * I.e. let's say you're testing class A which interacts with URLEncoder then
+ * you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { SystemClassUser.class })
+public class SystemClassUserTest {
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ expect(URLEncoder.encode("string", "enc")).andReturn("something");
+ replayAll();
+
+ assertEquals("something", new SystemClassUser().performEncode());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = createMock(Runtime.class);
+ Process processMock = createMock(Process.class);
+
+ expect(Runtime.getRuntime()).andReturn(runtimeMock);
+ expect(runtimeMock.exec("command")).andReturn(processMock);
+
+ replayAll();
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStaticPartial(System.class, "nanoTime");
+
+ expect(System.nanoTime()).andReturn(2L);
+
+ replayAll();
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+ expectLastCall().once();
+
+ replayAll();
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ mockStaticPartial(System.class, "getProperty");
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ expect(String.format(string, args)).andReturn(returnValue);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingStaticVoidMethodWorks() throws Exception {
+ mockStatic(Thread.class);
+
+ Thread.sleep(anyLong());
+ expectLastCall().once();
+
+ replayAll();
+
+ long startTime = System.currentTimeMillis();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.threadSleep();
+ long endTime = System.currentTimeMillis();
+ assertTrue(endTime - startTime < 5000);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInstanceMethodOfFinalSystemClassWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnection = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andStubReturn(urlConnection);
+
+ replayAll();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(urlConnection, systemClassUser.useURL(url));
+ verifyAll();
+ }
+
+ @Test
+ public void mockingURLWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnectionMock = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andReturn(urlConnectionMock);
+
+ replayAll();
+
+ assertSame(url.openConnection(), urlConnectionMock);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingFinalMethodsInSystemClassesWorks() throws Exception {
+ ClassLoader cl1 = createMock(ClassLoader.class);
+ ClassLoader cl2 = createMock(ClassLoader.class);
+
+ expect(cl1.getParent()).andReturn(cl2);
+
+ replayAll();
+
+ assertSame(cl1.getParent(), cl2);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInetAddressWorks() throws Exception {
+ final InetAddress mock = createMock(InetAddress.class);
+ mockStatic(InetAddress.class);
+
+ expect(InetAddress.getLocalHost()).andReturn(mock);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(mock, systemClassUser.getLocalHost());
+
+ verifyAll();
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/RunWithHierarchyTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/RunWithHierarchyTest.java
new file mode 100644
index 0000000..ac6a4d7
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/RunWithHierarchyTest.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.testhierarchy;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import samples.finalmocking.FinalDemo;
+
+//@RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class RunWithHierarchyTest extends TestParent {
+
+ @Test
+ public void testname() throws Exception {
+
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/TestParent.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/TestParent.java
new file mode 100644
index 0000000..53c2f89
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/testhierarchy/TestParent.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.testhierarchy;
+
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+ at RunWith(PowerMockRunner.class)
+public abstract class TestParent {
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/verify/AssertVerifyWorksTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/verify/AssertVerifyWorksTest.java
new file mode 100644
index 0000000..3883da0
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/verify/AssertVerifyWorksTest.java
@@ -0,0 +1,40 @@
+package samples.junit4.verify;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expectLastCall;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * This test asserts that the
+ * http://code.google.com/p/powermock/issues/detail?id=73 issue is resolved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticHelper.class, StaticService.class })
+public class AssertVerifyWorksTest {
+
+ @Test
+ public void testMockStaticWorks() throws Exception {
+ mockStaticPartial(StaticService.class, "sayHello");
+ mockStatic(StaticHelper.class);
+
+ StaticService.sayHello();
+ expectLastCall().once();
+
+ StaticHelper.sayHelloHelper();
+ expectLastCall().once();
+
+ replay(StaticService.class);
+ replay(StaticHelper.class);
+
+ StaticService.assertThatVerifyWorksForMultipleMocks();
+
+ verify(StaticService.class);
+ verify(StaticHelper.class);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/whitebox/PowerMockConstructorFiltrationTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/whitebox/PowerMockConstructorFiltrationTest.java
new file mode 100644
index 0000000..1b902ea
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/junit4/whitebox/PowerMockConstructorFiltrationTest.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.whitebox;
+
+import org.junit.Test;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import samples.whitebox.ClassWithPowerMockGeneratedConstructor;
+
+import java.lang.reflect.Constructor;
+
+import static org.junit.Assert.assertEquals;
+
+public class PowerMockConstructorFiltrationTest {
+ @Test
+ public void findUniqueConstructorOrThrowExceptionFiltersPowerMockConstructors() throws Exception {
+ Constructor<?> actualConstructor = WhiteboxImpl.findUniqueConstructorOrThrowException(ClassWithPowerMockGeneratedConstructor.class,
+ (Object) null);
+ assertEquals(ClassWithPowerMockGeneratedConstructor.class.getConstructor(String.class), actualConstructor);
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/methodhierarchy/MethodInvocationDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/methodhierarchy/MethodInvocationDemoTest.java
new file mode 100644
index 0000000..4650e9a
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/methodhierarchy/MethodInvocationDemoTest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.methodhierarchy;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test that verifies that it's possible to invoke and create partial mocks of
+ * private and/protected methods in a hierarchy.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MethodInvocationDemo.class })
+public class MethodInvocationDemoTest {
+
+ @Test
+ public void testCreatePartialMockForAProtectedMethodInASubclass() throws Exception {
+ final String value = "another string";
+ final String getTheStringMethodName = "getTheString";
+ MethodInvocationDemo tested = createPartialMock(MethodInvocationDemo.class, getTheStringMethodName);
+
+ expect(tested.getTheString()).andReturn(value);
+
+ replay(tested);
+
+ assertEquals(value, Whitebox.invokeMethod(tested, "getString"));
+
+ verify(tested);
+ }
+
+ @Test
+ @Ignore("Mabey this is impossible to achieve")
+ public void testCreatePartialMockForAProtectedMethodInASpecificSubclass() throws Exception {
+ final String value = "another string";
+ final String getTheStringMethodName = "getTheString";
+ MethodInvocationDemo tested = createPartialMock(MethodInvocationDemo.class, MethodInvocationDemoGrandParent.class, getTheStringMethodName);
+
+ expectPrivate(tested, getTheStringMethodName, MethodInvocationDemoGrandParent.class).andReturn(value);
+
+ replay(tested);
+
+ assertEquals("MethodInvocationDemoParent wrapped " + value, tested.getTheString());
+
+ verify(tested);
+ }
+
+ @Test
+ public void testWhenClassUnderTestIsAnAnonymousInnerClass() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo() {
+
+ };
+
+ assertEquals("MethodInvocationDemoParent wrapped a string from MethodInvocationDemoGrandParent", Whitebox.invokeMethod(tested, "getString"));
+ }
+
+ @Test
+ public void testInvokePrivateMethodInSuperClassWhenClassUnderTestIsAnAnonymousInnerClass() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo() {
+
+ };
+
+ assertEquals("MethodInvocationDemoParent", Whitebox.invokeMethod(tested, MethodInvocationDemoParent.class, "getString"));
+ }
+
+ @Test
+ public void testInvokeProtectedMethodWhenClassUnderTestIsAnAnonymousInnerClass() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo() {
+
+ };
+
+ assertEquals("MethodInvocationDemoParent wrapped a string from MethodInvocationDemoGrandParent", tested.getTheString());
+ }
+
+ @Test
+ public void testInvokeProtectedMethodWhenClassUnderTestIsAnAnonymousInnerClassUsingWithbox() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo() {
+
+ };
+
+ assertEquals("MethodInvocationDemoParent wrapped a string from MethodInvocationDemoGrandParent", Whitebox.invokeMethod(tested, "getTheString"));
+ }
+
+ @Test
+ public void testInvokeSpecificMethodInHierarchy() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo();
+
+ assertEquals("MethodInvocationDemoGrandParent", Whitebox.invokeMethod(tested, MethodInvocationDemoGrandParent.class, "getString",
+ (Object[]) new Class<?>[0]));
+ }
+
+ @Test
+ public void testInvokeSpecificMethodInHierarchyWithArguments() throws Exception {
+ MethodInvocationDemo tested = new MethodInvocationDemo();
+
+ assertEquals("MethodInvocationDemoGrandParent: 2", Whitebox.invokeMethod(tested, MethodInvocationDemoGrandParent.class, "getString",
+ new Class<?>[] { int.class }, 2));
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/packageprivate/PackagePrivateClassTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/packageprivate/PackagePrivateClassTest.java
new file mode 100644
index 0000000..82626ff
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/packageprivate/PackagePrivateClassTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.packageprivate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Verifies that the issue at
+ * http://code.google.com/p/powermock/issues/detail?id=32 is solved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PackagePrivateClass.class)
+public class PackagePrivateClassTest {
+
+ @Test
+ public void testMockAPackagePrivateClass() throws Exception {
+ final String returnAValueMethodName = "returnAValue";
+ final int expected = 23;
+
+ PackagePrivateClass tested = createPartialMock(PackagePrivateClass.class, returnAValueMethodName);
+ expectPrivate(tested, returnAValueMethodName).andReturn(expected);
+
+ replay(tested);
+
+ assertEquals(expected, tested.getValue());
+
+ verify(tested);
+ }
+
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressDefaultConstructorTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressDefaultConstructorTest.java
new file mode 100644
index 0000000..3002b31
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressDefaultConstructorTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.suppressconstructor;
+
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static junit.framework.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberMatcher.defaultConstructorIn;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(AppaleList.class)
+public class SuppressDefaultConstructorTest {
+
+ @Test
+ public void powerMockCanSuppressDefaultConstructor() {
+ suppress(defaultConstructorIn(AppaleList.class));
+ AppaleList appaleList = new AppaleList();
+ String str = appaleList.getAll();
+ assertEquals(str, "str");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void powerMockSuppressesOnlyDefaultConstructorWhenUsingDefaultConstructorIn() {
+ suppress(defaultConstructorIn(AppaleList.class));
+ new AppaleList("something");
+ }
+
+ @Test
+ public void powerMockCanSuppressDefaultConstructorUsingConstructorMethod() {
+ suppress(constructor(AppaleList.class, new Class[0]));
+ AppaleList appaleList = new AppaleList();
+ String str = appaleList.getAll();
+ assertEquals(str, "str");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void powerMockSuppressesOnlyDefaultConstructorWhenApplicable() {
+ suppress(constructor(AppaleList.class, new Class[0]));
+ new AppaleList("something");
+ }
+}
diff --git a/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressSpecificConstructorDemoTest.java b/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressSpecificConstructorDemoTest.java
new file mode 100644
index 0000000..50a2996
--- /dev/null
+++ b/modules/module-test/easymock/junit4-test/src/test/java/samples/suppressconstructor/SuppressSpecificConstructorDemoTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.fail;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { SuppressSpecificConstructorDemo.class, SuppressSpecificConstructorDemoTest.class })
+public class SuppressSpecificConstructorDemoTest {
+
+ @Test
+ public void testMockStringConstructor() throws Exception {
+ suppress(constructor(SuppressSpecificConstructorDemo.class, String.class));
+
+ // This should be fine
+ new SuppressSpecificConstructorDemo("This expection should not occur");
+ // This should not be fine!
+ try {
+ new SuppressSpecificConstructorDemo();
+ fail("Should have thrown IllegalStateException!");
+ } catch (IllegalStateException e) {
+ // assertEquals("", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/pom.xml b/modules/module-test/easymock/junit410-test/pom.xml
new file mode 100644
index 0000000..ed85179
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit410</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.10.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.10</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/assume/AssumeForJUnit410Test.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/assume/AssumeForJUnit410Test.java
new file mode 100644
index 0000000..65442dc
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/assume/AssumeForJUnit410Test.java
@@ -0,0 +1,17 @@
+package samples.junit410.assume;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assume.assumeTrue;
+
+ at RunWith(PowerMockRunner.class)
+public class AssumeForJUnit410Test {
+
+ @Test
+ public void assumesWorkWithPowerMockForJUnit410() throws Exception {
+ // When
+ assumeTrue(false);
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewDemoTest.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewDemoTest.java
new file mode 100644
index 0000000..c88c44a
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewDemoTest.java
@@ -0,0 +1,658 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit410.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate new instance mocking using expectNew(..).
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class ExpectNewDemoTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replay(myClassMock, MyClass.class);
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock, MyClass.class);
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ expectNew(MyClass.class).andThrow(new RuntimeException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testPreviousProblemsWithByteCodeManipulation() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+ expect(myClassMock1.getMessage()).andReturn("Hello");
+ expect(myClassMock1.getMessage()).andReturn("World");
+ replay(myClassMock1);
+ assertEquals("Hello", myClassMock1.getMessage());
+ assertEquals("World", myClassMock1.getMessage());
+ verify(myClassMock1);
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ MyClass myClassMock2 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1);
+ expectNew(MyClass.class).andReturn(myClassMock2);
+
+ expect(myClassMock1.getMessage()).andReturn("Hello ");
+ expect(myClassMock2.getMessage()).andReturn("World");
+
+ replay(myClassMock1, myClassMock2, MyClass.class);
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock1, myClassMock2, MyClass.class);
+
+ assertEquals("Hello World", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.simpleMultipleNew();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleMultipleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_lowerBoundLessThan0() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ try {
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-20, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertEquals("minimum must be >= 0", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThan0() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-1, -2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThanLowerBound() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(10, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_OK() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(1, 5);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_anyTimes() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).anyTimes();
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_notWithinRange() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(5, 7);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: between 5 and 7, actual: 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ expectNew(DataInputStream.class, new Object[] { null }).andThrow(new RuntimeException("error"));
+
+ replay(ExpectNewDemo.class, DataInputStream.class);
+
+ InputStream stream = tested.alternativePath();
+
+ verify(ExpectNewDemo.class, DataInputStream.class);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ expectNew(VarArgsConstructorDemo.class, firstString, secondString).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllMessages()).andReturn(new String[] { firstString, secondString });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ expectNew(VarArgsConstructorDemo.class, object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = createMock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ @Override
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ expectNew(VarArgsConstructorDemo.class, serviceSubTypeInstance, serviceMock).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllServices()).andReturn(new Service[] { serviceMock });
+
+ replay(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verify(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, aryEq(byteArrayOne), aryEq(byteArrayTwo)).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo, byteArrayThree).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ try {
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "\n Unexpected constructor call samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 4):"
+ + "\n samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 2): expected: 1, actual: 0",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.makeDate();
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertTrue(e.getMessage().contains(MyClass.class.getName() + "(): expected: 1, actual: 0"));
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewOfFinalSystemClassTest.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewOfFinalSystemClassTest.java
new file mode 100644
index 0000000..916785b
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/expectnew/ExpectNewOfFinalSystemClassTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit410.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewOfFinalSystemClassDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { ExpectNewOfFinalSystemClassDemo.class })
+public class ExpectNewOfFinalSystemClassTest {
+
+ @Test
+ public void assertThatExpectNewWorksForFinalSystemClasses() throws Exception {
+ String mock = createMock(String.class);
+
+ expectNew(String.class, "My String").andReturn(mock);
+ expect(mock.charAt(0)).andReturn('o');
+
+ replayAll();
+ assertEquals('o', new ExpectNewOfFinalSystemClassDemo().getFirstChar());
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/AssertThatJUnit410RulesWorks.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/AssertThatJUnit410RulesWorks.java
new file mode 100644
index 0000000..58d45d0
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/AssertThatJUnit410RulesWorks.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit410.rules;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+/**
+ * This test demonstrates that JUnit 4.10 rules works together with PowerMock
+ */
+ at RunWith(PowerMockRunner.class)
+public class AssertThatJUnit410RulesWorks {
+ private static Object BEFORE = new Object();
+
+ private List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertThatJUnit410RulesWorks() throws Exception {
+ assertEquals(1, objects.size());
+ assertSame(BEFORE, objects.get(0));
+ assertEquals("assertThatJUnit410RulesWorks", testName.getMethodName());
+ }
+
+ private class MyRule implements MethodRule {
+ public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ base.evaluate();
+ }
+ };
+ }
+ }
+
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/ExceptionHandlingRuleTest.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/ExceptionHandlingRuleTest.java
new file mode 100644
index 0000000..ddf0d81
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/ExceptionHandlingRuleTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit410.rules;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.junit410.rules.impl.SimpleEasyMockJUnitRule;
+import samples.rule.SimpleThingCreator;
+import samples.rule.SimpleThingImpl;
+import samples.rule.ThingToTest;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleThingCreator.class)
+public class ExceptionHandlingRuleTest {
+
+ @Rule
+ public SimpleEasyMockJUnitRule mocks = new SimpleEasyMockJUnitRule();
+
+ private SimpleThingImpl simpleThingMock = mocks.createMock(SimpleThingImpl.class);
+
+ // object under test
+ private ThingToTest testThing;
+
+ @Before
+ public void setUp() throws Exception {
+ mockStatic(SimpleThingCreator.class);
+ expect(SimpleThingCreator.createSimpleThing()).andReturn(simpleThingMock);
+ replay(SimpleThingCreator.class);
+
+ verify(SimpleThingCreator.class);
+ }
+
+ @Test
+ @Ignore("This test SHOULD fail but how do we expect it when verification happens in the rule?")
+ public void exceptionThrownByRuleFailsTheTest() throws Exception {
+ final String expectedName = "Smith";
+ expect(simpleThingMock.getThingName()).andReturn(expectedName);
+ mocks.replay();
+
+ assertEquals("wrong name", expectedName, testThing.getName());
+ // verify will be called by rule
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/NoRuleAssertionErrorTest.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/NoRuleAssertionErrorTest.java
new file mode 100644
index 0000000..e2bba5a
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/NoRuleAssertionErrorTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit410.rules;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertTrue;
+
+ at RunWith(PowerMockRunner.class)
+public class NoRuleAssertionErrorTest {
+
+ @Test(expected = AssertionError.class)
+ public void assertionErrorIsThrownOnFailureWhenNoRulesDefined() throws Exception {
+ assertTrue(false);
+ }
+}
diff --git a/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/impl/SimpleEasyMockJUnitRule.java b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/impl/SimpleEasyMockJUnitRule.java
new file mode 100644
index 0000000..76d7c4b
--- /dev/null
+++ b/modules/module-test/easymock/junit410-test/src/test/java/samples/junit410/rules/impl/SimpleEasyMockJUnitRule.java
@@ -0,0 +1,69 @@
+package samples.junit410.rules.impl;
+
+import org.easymock.IMocksControl;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import static org.easymock.EasyMock.createControl;
+
+/**
+ * A JUnit rule that resets all mocks before each test and verifies the mocks after the test
+ */
+public class SimpleEasyMockJUnitRule implements MethodRule {
+
+ final IMocksControl control;
+ boolean recording = true;
+ public Error caughtError = null;
+
+ /**
+ * Create the rule using the default EasyMock.createControl()
+ */
+ public SimpleEasyMockJUnitRule() {
+ this(createControl());
+ }
+
+ /**
+ * Create the rule using the IMocksControl that you provide
+ *
+ * @param control
+ * The provided IMocksControl to use for testing
+ */
+ public SimpleEasyMockJUnitRule(IMocksControl control) {
+ this.control = control;
+ }
+
+ public <T> T createMock(Class<T> toMock) {
+ return control.createMock(toMock);
+ }
+
+ public void reset() {
+ recording = true;
+ control.reset();
+ }
+
+ public void replay() {
+ recording = false;
+ control.replay();
+ }
+
+ public void verify() {
+ control.verify();
+ }
+
+ @Override
+ public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ reset();
+ base.evaluate();
+ if (!recording) {
+ verify(); // only verify if no exceptions were thrown
+ }
+ }
+ };
+ }
+
+}
diff --git a/modules/module-test/easymock/junit45-test/pom.xml b/modules/module-test/easymock/junit45-test/pom.xml
new file mode 100644
index 0000000..c1dbac0
--- /dev/null
+++ b/modules/module-test/easymock/junit45-test/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit45</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.5.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.5</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyClass.java b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyClass.java
new file mode 100644
index 0000000..880e570
--- /dev/null
+++ b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyClass.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.modules.test.junit45.failure;
+
+public class MyClass {
+
+ public int sum(int a, int b) throws MyException {
+ if (MyUtils.isValid(a))
+ throw new MyException();
+ else
+ return a + b;
+ }
+
+}
diff --git a/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyException.java b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyException.java
new file mode 100644
index 0000000..f00f9a6
--- /dev/null
+++ b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyException.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.modules.test.junit45.failure;
+
+public class MyException extends Exception {
+ private static final long serialVersionUID = -222072316863858540L;
+
+}
diff --git a/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyUtils.java b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyUtils.java
new file mode 100644
index 0000000..7bb301f
--- /dev/null
+++ b/modules/module-test/easymock/junit45-test/src/main/java/demo/org/powermock/modules/test/junit45/failure/MyUtils.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.modules.test.junit45.failure;
+
+public class MyUtils {
+
+ public static boolean isValid(int a) {
+ return a > 10;
+ }
+
+}
diff --git a/modules/module-test/easymock/junit45-test/src/test/java/demo/org/powermock/modules/test/junit45/failure/AssertThatJUnit45FailuresWorkTest.java b/modules/module-test/easymock/junit45-test/src/test/java/demo/org/powermock/modules/test/junit45/failure/AssertThatJUnit45FailuresWorkTest.java
new file mode 100644
index 0000000..6b6a4fc
--- /dev/null
+++ b/modules/module-test/easymock/junit45-test/src/test/java/demo/org/powermock/modules/test/junit45/failure/AssertThatJUnit45FailuresWorkTest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package demo.org.powermock.modules.test.junit45.failure;
+
+import org.easymock.EasyMock;
+import org.junit.Test;
+import org.junit.internal.AssumptionViolatedException;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl;
+
+import static org.junit.Assert.assertTrue;
+
+/**
+ * This test asserts that JUnit 4.5 failures works as expected. Previously the
+ * {@link PowerMockJUnit44RunnerDelegateImpl} got a {@link NoClassDefFoundError}
+ * when trying to load JUnit 4.4's {@link AssumptionViolatedException} which has
+ * been moved in JUnit 4.5. Thanks to Manuel Fern�ndez S�nchez de la Blanca for
+ * creating this test case to prove the issue.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MyUtils.class)
+public class AssertThatJUnit45FailuresWorkTest {
+
+ @Test(expected = AssumptionViolatedException.class)
+ public void testAssumptionViolatedException() throws MyException {
+ throw new AssumptionViolatedException("Not true!");
+ }
+
+ @Test(expected = MyException.class)
+ public void testSum() throws MyException {
+ PowerMock.mockStatic(MyUtils.class);
+ EasyMock.expect(MyUtils.isValid(1)).andReturn(true);
+ PowerMock.replay(MyUtils.class);
+
+ MyClass myclass = new MyClass();
+ int result = myclass.sum(1, 2);
+ PowerMock.verify(MyUtils.class);
+
+ assertTrue(result == 3);
+ }
+
+ @Test(expected = MyException.class)
+ public void testSum2() throws MyException {
+ MyClass myclass = new MyClass();
+ myclass.sum(100, 2);
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/pom.xml b/modules/module-test/easymock/junit47-test/pom.xml
new file mode 100644
index 0000000..6cd332d
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit47</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.7.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java
new file mode 100644
index 0000000..1e7cdc6
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/annotationbased/FinalDemoWithAnnotationInjectionAndFieldDefaulterTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PowerMockListener;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.testlisteners.FieldDefaulter;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with multiple test
+ * listeners for JUnit 4.7.
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+ at PowerMockListener( { FieldDefaulter.class })
+public class FinalDemoWithAnnotationInjectionAndFieldDefaulterTest {
+
+ @SuppressWarnings("unused")
+ // Asserts that the FieldDefaulter handles primitive types.
+ private int intType = 6;
+
+ @Mock
+ private FinalDemo tested;
+
+ @Test
+ public void testSay() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java
new file mode 100644
index 0000000..43567fc
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewDemoTest.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate new instance mocking using expectNew(..).
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class ExpectNewDemoTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replay(myClassMock, MyClass.class);
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock, MyClass.class);
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ expectNew(MyClass.class).andThrow(new RuntimeException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testPreviousProblemsWithByteCodeManipulation() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+ expect(myClassMock1.getMessage()).andReturn("Hello");
+ expect(myClassMock1.getMessage()).andReturn("World");
+ replay(myClassMock1);
+ assertEquals("Hello", myClassMock1.getMessage());
+ assertEquals("World", myClassMock1.getMessage());
+ verify(myClassMock1);
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ MyClass myClassMock2 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1);
+ expectNew(MyClass.class).andReturn(myClassMock2);
+
+ expect(myClassMock1.getMessage()).andReturn("Hello ");
+ expect(myClassMock2.getMessage()).andReturn("World");
+
+ replay(myClassMock1, myClassMock2, MyClass.class);
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock1, myClassMock2, MyClass.class);
+
+ assertEquals("Hello World", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.simpleMultipleNew();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleMultipleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_lowerBoundLessThan0() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ try {
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-20, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertEquals("minimum must be >= 0", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThan0() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-1, -2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThanLowerBound() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(10, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_OK() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(1, 5);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_anyTimes() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).anyTimes();
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_notWithinRange() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(5, 7);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: between 5 and 7, actual: 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ expectNew(DataInputStream.class, new Object[] { null }).andThrow(new RuntimeException("error"));
+
+ replay(ExpectNewDemo.class, DataInputStream.class);
+
+ InputStream stream = tested.alternativePath();
+
+ verify(ExpectNewDemo.class, DataInputStream.class);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ expectNew(VarArgsConstructorDemo.class, firstString, secondString).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllMessages()).andReturn(new String[] { firstString, secondString });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ expectNew(VarArgsConstructorDemo.class, object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = createMock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ expectNew(VarArgsConstructorDemo.class, serviceSubTypeInstance, serviceMock).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllServices()).andReturn(new Service[] { serviceMock });
+
+ replay(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verify(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, aryEq(byteArrayOne), aryEq(byteArrayTwo)).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo, byteArrayThree).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ try {
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "\n Unexpected constructor call samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 4):"
+ + "\n samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 2): expected: 1, actual: 0",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.makeDate();
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertTrue(e.getMessage().contains(MyClass.class.getName() + "(): expected: 1, actual: 0"));
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java
new file mode 100644
index 0000000..a4d3657
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/expectnew/ExpectNewOfFinalSystemClassTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewOfFinalSystemClassDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { ExpectNewOfFinalSystemClassDemo.class })
+public class ExpectNewOfFinalSystemClassTest {
+
+ @Test
+ public void assertThatExpectNewWorksForFinalSystemClasses() throws Exception {
+ String mock = createMock(String.class);
+
+ expectNew(String.class, "My String").andReturn(mock);
+ expect(mock.charAt(0)).andReturn('o');
+
+ replayAll();
+ assertEquals('o', new ExpectNewOfFinalSystemClassDemo().getFirstChar());
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/AssertThatJUnit47RulesWorks.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/AssertThatJUnit47RulesWorks.java
new file mode 100644
index 0000000..a8bf583
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/AssertThatJUnit47RulesWorks.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.rules;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+/**
+ * This test demonstrates that JUnit 4.7 rules works together with PowerMock
+ */
+ at RunWith(PowerMockRunner.class)
+public class AssertThatJUnit47RulesWorks {
+ private static Object BEFORE = new Object();
+
+ private List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertThatJUnit47RulesWorks() throws Exception {
+ assertEquals(1, objects.size());
+ assertSame(BEFORE, objects.get(0));
+ assertEquals("assertThatJUnit47RulesWorks", testName.getMethodName());
+ }
+
+ private class MyRule implements MethodRule {
+ @Override
+ public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ base.evaluate();
+ }
+ };
+ }
+ }
+
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/NoRuleAssertionErrorTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/NoRuleAssertionErrorTest.java
new file mode 100644
index 0000000..3a7e2b1
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/NoRuleAssertionErrorTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.rules;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertTrue;
+
+ at RunWith(PowerMockRunner.class)
+public class NoRuleAssertionErrorTest {
+
+ @Test(expected = AssertionError.class)
+ public void assertionErrorIsThrownOnFailureWhenNoRulesDefined() throws Exception {
+ assertTrue(false);
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/RuleOrderTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/RuleOrderTest.java
new file mode 100644
index 0000000..ff04b83
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/RuleOrderTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.rules;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+ at RunWith(PowerMockRunner.class)
+public class RuleOrderTest {
+
+ private static final String EMPTY_STRING = "";
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ private String temporaryFileName = EMPTY_STRING;
+
+ @Before
+ public void setup() throws Exception {
+ temporaryFileName = folder.newFile("tempFile").getPath();
+ }
+
+ @Test
+ public void rulesAreExecutedBeforeSetupMethods() throws Exception {
+ assertThat(temporaryFileName, not(nullValue()));
+ assertThat(temporaryFileName, not(equalTo(EMPTY_STRING)));
+ }
+}
diff --git a/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/ThrowingRuleTest.java b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/ThrowingRuleTest.java
new file mode 100644
index 0000000..3f364bc
--- /dev/null
+++ b/modules/module-test/easymock/junit47-test/src/test/java/samples/junit4/rules/ThrowingRuleTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit4.rules;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Asserts that expected expectation rules also works with the PowerMock JUnit
+ * 4.7 runner. Asserts that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=179">issue 179</a>
+ * has been resolved. Thanks to Andrei Ivanov for finding this bug.
+ */
+ at RunWith(PowerMockRunner.class)
+public class ThrowingRuleTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void throwsNullPointerException() {
+ thrown.expect(RuntimeException.class);
+ throw new RuntimeException();
+ }
+
+ @Test
+ public void throwsNullPointerExceptionWithMessage() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("What happened?");
+ throw new NullPointerException("What happened?");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void unexpectAssertionErrorFailsTestCorrectly() {
+ throw new NullPointerException("What happened?");
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/pom.xml b/modules/module-test/easymock/junit48-test/pom.xml
new file mode 100644
index 0000000..fb140a5
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/pom.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-junit48</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with JUnit 4.8.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.8.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewDemoTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewDemoTest.java
new file mode 100644
index 0000000..bfe6b45
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewDemoTest.java
@@ -0,0 +1,657 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.easymock.EasyMock.*;
+import static org.easymock.EasyMock.expectLastCall;
+import static org.junit.Assert.*;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate new instance mocking using expectNew(..).
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class ExpectNewDemoTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ expectNew(MyClass.class).andThrow(new IOException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage()).andReturn("Hello altered World");
+
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ expect(myClassMock.getMessage("test")).andReturn("Hello altered World");
+ replay(myClassMock, MyClass.class);
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock, MyClass.class);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = createMock(MyClass.class);
+ expectNew(MyClass.class).andReturn(myClassMock);
+
+ myClassMock.voidMethod();
+ expectLastCall().times(1);
+
+ replay(myClassMock, MyClass.class);
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock, MyClass.class);
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ expectNew(MyClass.class).andThrow(new RuntimeException(expectedFailMessage));
+
+ replay(MyClass.class);
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verify(MyClass.class);
+ }
+
+ @Test
+ public void testPreviousProblemsWithByteCodeManipulation() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+ expect(myClassMock1.getMessage()).andReturn("Hello");
+ expect(myClassMock1.getMessage()).andReturn("World");
+ replay(myClassMock1);
+ assertEquals("Hello", myClassMock1.getMessage());
+ assertEquals("World", myClassMock1.getMessage());
+ verify(myClassMock1);
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ MyClass myClassMock2 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1);
+ expectNew(MyClass.class).andReturn(myClassMock2);
+
+ expect(myClassMock1.getMessage()).andReturn("Hello ");
+ expect(myClassMock2.getMessage()).andReturn("World");
+
+ replay(myClassMock1, myClassMock2, MyClass.class);
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock1, myClassMock2, MyClass.class);
+
+ assertEquals("Hello World", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.simpleMultipleNew();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(2);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected constructor call samples.newmocking.MyClass():"
+ + "\n samples.newmocking.MyClass(): expected: 2, actual: 3", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(3);
+
+ replay(myClassMock1, MyClass.class);
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleSingleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).atLeastOnce();
+
+ replay(myClassMock1, MyClass.class);
+ tested.simpleMultipleNew();
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_lowerBoundLessThan0() throws Exception {
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ try {
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-20, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertEquals("minimum must be >= 0", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThan0() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(-1, -2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_upperBoundLessThanLowerBound() throws Exception {
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+ try {
+ expectNew(MyClass.class).andReturn(myClassMock1).times(10, 2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ assertTrue(e.getMessage().contains("<="));
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_OK() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(1, 5);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_anyTimes() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).anyTimes();
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ verify(myClassMock1, MyClass.class);
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withRange_notWithinRange() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(5, 7);
+
+ replay(myClassMock1, MyClass.class);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: between 5 and 7, actual: 3",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ expectNew(DataInputStream.class, new Object[] { null }).andThrow(new RuntimeException("error"));
+
+ replay(ExpectNewDemo.class, DataInputStream.class);
+
+ InputStream stream = tested.alternativePath();
+
+ verify(ExpectNewDemo.class, DataInputStream.class);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).times(4);
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("\n Expectation failure on verify:" + "\n samples.newmocking.MyClass(): expected: 4, actual: 3", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ expectNew(VarArgsConstructorDemo.class, firstString, secondString).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllMessages()).andReturn(new String[] { firstString, secondString });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ expectNew(VarArgsConstructorDemo.class, object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = createMock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ expectNew(VarArgsConstructorDemo.class, serviceSubTypeInstance, serviceMock).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getAllServices()).andReturn(new Service[] { serviceMock });
+
+ replay(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verify(serviceMock, VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, aryEq(byteArrayOne), aryEq(byteArrayTwo)).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayOne });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo, byteArrayThree).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = createMock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ expectNew(VarArgsConstructorDemo.class, byteArrayOne, byteArrayTwo).andReturn(varArgsConstructorDemoMock);
+ expect(varArgsConstructorDemoMock.getByteArrays()).andReturn(new byte[][] { byteArrayTwo });
+
+ replay(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verify(VarArgsConstructorDemo.class, varArgsConstructorDemoMock);
+ }
+
+ @Test
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = createMock(ExpectNewServiceUser.class);
+ Service serviceMock = createMock(Service.class);
+
+ expectNew(ExpectNewServiceUser.class, serviceMock, numberOfTimes).andReturn(expectNewServiceImplMock);
+ expect(expectNewServiceImplMock.useService()).andReturn(expected);
+
+ replay(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+
+ try {
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+ verify(expectNewServiceImplMock, serviceMock, ExpectNewServiceUser.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "\n Unexpected constructor call samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 4):"
+ + "\n samples.expectnew.ExpectNewServiceUser(EasyMock for interface samples.Service, 2): expected: 1, actual: 0",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = createMock(MyClass.class);
+
+ expectNew(MyClass.class).andReturn(myClassMock1).once();
+
+ replay(myClassMock1, MyClass.class);
+ try {
+ tested.makeDate();
+ verify(myClassMock1, MyClass.class);
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertTrue(e.getMessage().contains(MyClass.class.getName() + "(): expected: 1, actual: 0"));
+ }
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewOfFinalSystemClassTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewOfFinalSystemClassTest.java
new file mode 100644
index 0000000..53395f1
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/expectnew/ExpectNewOfFinalSystemClassTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.expectnew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewOfFinalSystemClassDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { ExpectNewOfFinalSystemClassDemo.class })
+public class ExpectNewOfFinalSystemClassTest {
+
+ @Test
+ public void assertThatExpectNewWorksForFinalSystemClasses() throws Exception {
+ String mock = createMock(String.class);
+
+ expectNew(String.class, "My String").andReturn(mock);
+ expect(mock.charAt(0)).andReturn('o');
+
+ replayAll();
+ assertEquals('o', new ExpectNewOfFinalSystemClassDemo().getFirstChar());
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/AssertThatJUnit48RulesWorks.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/AssertThatJUnit48RulesWorks.java
new file mode 100644
index 0000000..abd6a3f
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/AssertThatJUnit48RulesWorks.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.rules;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+/**
+ * This test demonstrates that JUnit 4.7 rules works together with PowerMock
+ */
+ at RunWith(PowerMockRunner.class)
+public class AssertThatJUnit48RulesWorks {
+ private static Object BEFORE = new Object();
+
+ private List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertThatJUnit47RulesWorks() throws Exception {
+ assertEquals(1, objects.size());
+ assertSame(BEFORE, objects.get(0));
+ assertEquals("assertThatJUnit47RulesWorks", testName.getMethodName());
+ }
+
+ private class MyRule implements MethodRule {
+ @Override
+ public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ base.evaluate();
+ }
+ };
+ }
+ }
+
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ExceptionHandlingRuleTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ExceptionHandlingRuleTest.java
new file mode 100644
index 0000000..73d6b46
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ExceptionHandlingRuleTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.junit48.rules;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.junit48.rules.impl.SimpleEasyMockJUnitRule;
+import samples.rule.SimpleThingCreator;
+import samples.rule.SimpleThingImpl;
+import samples.rule.ThingToTest;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleThingCreator.class)
+public class ExceptionHandlingRuleTest {
+
+ @Rule
+ public SimpleEasyMockJUnitRule mocks = new SimpleEasyMockJUnitRule();
+
+ private SimpleThingImpl simpleThingMock = mocks.createMock(SimpleThingImpl.class);
+
+ // object under test
+ private ThingToTest testThing;
+
+ @Before
+ public void setUp() throws Exception {
+ mockStatic(SimpleThingCreator.class);
+ expect(SimpleThingCreator.createSimpleThing()).andReturn(simpleThingMock);
+ replay(SimpleThingCreator.class);
+
+ verify(SimpleThingCreator.class);
+ }
+
+ @Test
+ @Ignore("This test SHOULD fail but how do we expect it when verification happens in the rule?")
+ public void exceptionThrownByRuleFailsTheTest() throws Exception {
+ final String expectedName = "Smith";
+ expect(simpleThingMock.getThingName()).andReturn(expectedName);
+ mocks.replay();
+
+ assertEquals("wrong name", expectedName, testThing.getName());
+ // verify will be called by rule
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/NoRuleAssertionErrorTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/NoRuleAssertionErrorTest.java
new file mode 100644
index 0000000..0fe1ec1
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/NoRuleAssertionErrorTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.rules;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertTrue;
+
+ at RunWith(PowerMockRunner.class)
+public class NoRuleAssertionErrorTest {
+
+ @Test(expected = AssertionError.class)
+ public void assertionErrorIsThrownOnFailureWhenNoRulesDefined() throws Exception {
+ assertTrue(false);
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/RuleOrderTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/RuleOrderTest.java
new file mode 100644
index 0000000..9776546
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/RuleOrderTest.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.rules;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.CoreMatchers.*;
+import static org.junit.Assert.assertThat;
+
+ at RunWith(PowerMockRunner.class)
+public class RuleOrderTest {
+
+ private static final String EMPTY_STRING = "";
+
+ @Rule
+ public TemporaryFolder folder = new TemporaryFolder();
+
+ private String temporaryFileName = EMPTY_STRING;
+
+ @Before
+ public void setup() throws Exception {
+ temporaryFileName = folder.newFile("tempFile").getPath();
+ }
+
+ @Test
+ public void rulesAreExecutedBeforeSetupMethods() throws Exception {
+ assertThat(temporaryFileName, not(nullValue()));
+ assertThat(temporaryFileName, not(equalTo(EMPTY_STRING)));
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ThrowingRuleTest.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ThrowingRuleTest.java
new file mode 100644
index 0000000..75439ae
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/ThrowingRuleTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.junit48.rules;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ * Asserts that expected expectation rules also works with the PowerMock JUnit
+ * 4.7 runner. Asserts that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=179">issue 179</a>
+ * has been resolved. Thanks to Andrei Ivanov for finding this bug.
+ */
+ at RunWith(PowerMockRunner.class)
+public class ThrowingRuleTest {
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void throwsNullPointerException() {
+ thrown.expect(RuntimeException.class);
+ throw new RuntimeException();
+ }
+
+ @Test
+ public void throwsNullPointerExceptionWithMessage() {
+ thrown.expect(NullPointerException.class);
+ thrown.expectMessage("What happened?");
+ throw new NullPointerException("What happened?");
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void unexpectAssertionErrorFailsTestCorrectly() {
+ throw new NullPointerException("What happened?");
+ }
+}
diff --git a/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/impl/SimpleEasyMockJUnitRule.java b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/impl/SimpleEasyMockJUnitRule.java
new file mode 100644
index 0000000..ee3fc25
--- /dev/null
+++ b/modules/module-test/easymock/junit48-test/src/test/java/samples/junit48/rules/impl/SimpleEasyMockJUnitRule.java
@@ -0,0 +1,69 @@
+package samples.junit48.rules.impl;
+
+import org.easymock.IMocksControl;
+import org.junit.rules.MethodRule;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+
+import static org.easymock.EasyMock.createControl;
+
+/**
+ * A JUnit rule that resets all mocks before each test and verifies the mocks after the test
+ */
+public class SimpleEasyMockJUnitRule implements MethodRule {
+
+ final IMocksControl control;
+ boolean recording = true;
+ public Error caughtError = null;
+
+ /**
+ * Create the rule using the default EasyMock.createControl()
+ */
+ public SimpleEasyMockJUnitRule() {
+ this(createControl());
+ }
+
+ /**
+ * Create the rule using the IMocksControl that you provide
+ *
+ * @param control
+ * The provided IMocksControl to use for testing
+ */
+ public SimpleEasyMockJUnitRule(IMocksControl control) {
+ this.control = control;
+ }
+
+ public <T> T createMock(Class<T> toMock) {
+ return control.createMock(toMock);
+ }
+
+ public void reset() {
+ recording = true;
+ control.reset();
+ }
+
+ public void replay() {
+ recording = false;
+ control.replay();
+ }
+
+ public void verify() {
+ control.verify();
+ }
+
+ @Override
+ public Statement apply(final Statement base, final FrameworkMethod method, final Object target) {
+ return new Statement() {
+
+ @Override
+ public void evaluate() throws Throwable {
+ reset();
+ base.evaluate();
+ if (!recording) {
+ verify(); // only verify if no exceptions were thrown
+ }
+ }
+ };
+ }
+
+}
diff --git a/modules/module-test/easymock/pom.xml b/modules/module-test/easymock/pom.xml
new file mode 100644
index 0000000..02bca93
--- /dev/null
+++ b/modules/module-test/easymock/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with various test frameworks.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock.tests</groupId>
+ <artifactId>powermock-tests-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <modules>
+ <module>junit3-test</module>
+ <module>junit4-legacy-test</module>
+ <module>junit4-test</module>
+ <module>junit45-test</module>
+ <module>testng-test</module>
+ <module>testng-agent-test</module>
+ <module>junit47-test</module>
+ <module>junit48-test</module>
+ <module>junit410-test</module>
+ <module>junit4-agent</module>
+ </modules>
+</project>
diff --git a/modules/module-test/easymock/testng-agent-test/pom.xml b/modules/module-test/easymock/testng-agent-test/pom.xml
new file mode 100644
index 0000000..97d3d30
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-testng-agent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with TestNG and PowerMock java agent.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>6.9.10</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-agent</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoTest.java
new file mode 100644
index 0000000..2fbfcf7
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoTest.java
@@ -0,0 +1,36 @@
+package samples.testng.agent;
+
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly in TestNG.
+ */
+ at PrepareForTest
+public class AnnotationDemoTest extends PowerMockTestCase {
+
+ @Mock
+ private Service serviceMock;
+
+ @Test
+ public void assertInjectionWorked() throws Exception {
+ AnnotationDemo tested = new AnnotationDemo(serviceMock);
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ Assert.assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoWithBeforeMethodTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoWithBeforeMethodTest.java
new file mode 100644
index 0000000..b87771c
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/AnnotationDemoWithBeforeMethodTest.java
@@ -0,0 +1,44 @@
+package samples.testng.agent;
+
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly with before methods in
+ * TestNG.
+ */
+public class AnnotationDemoWithBeforeMethodTest extends PowerMockTestCase {
+
+ @Mock
+ private Service serviceMock;
+
+ private AnnotationDemo tested;
+
+ @BeforeMethod
+ public void setup() {
+ tested = new AnnotationDemo(serviceMock);
+ }
+
+ @Test
+ @PrepareForTest
+ public void assertInjectionWorked() throws Exception {
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ Assert.assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/FinalDemoTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/FinalDemoTest.java
new file mode 100644
index 0000000..a173f8b
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/FinalDemoTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.AssertJUnit;
+import org.testng.annotations.Test;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.testng.Assert.fail;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ * Test class to demonstrate non-static final mocking.
+ *
+ */
+ at PrepareForTest(FinalDemo.class)
+public class FinalDemoTest extends PowerMockTestCase {
+
+ @Test
+ public void testSay() throws Exception {
+ FinalDemo tested = createMock(FinalDemo.class);
+ String expected = "Hello altered World";
+ expect(tested.say("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.say("hello");
+
+ verify(tested);
+ AssertJUnit.assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.say(\"world\"):", e.getMessage());
+ }
+
+ }
+
+ @Test
+ public void testSayFinalNative() throws Exception {
+ FinalDemo tested = createMock(FinalDemo.class);
+ String expected = "Hello altered World";
+ expect(tested.sayFinalNative("hello")).andReturn("Hello altered World");
+ replay(tested);
+
+ String actual = tested.sayFinalNative("hello");
+
+ verify(tested);
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ tested.sayFinalNative("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("\n Unexpected method call FinalDemo.sayFinalNative(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticExtendsPowerMockTestCaseTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticExtendsPowerMockTestCaseTest.java
new file mode 100644
index 0000000..887cde8
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticExtendsPowerMockTestCaseTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticExtendsPowerMockTestCaseTest extends PowerMockTestCase {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ Assert.fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ Assert.assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.sayFinal("world");
+ Assert.fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ Assert.assertEquals("\n Unexpected method call StaticService.sayFinal(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticTest.java
new file mode 100644
index 0000000..0e77357
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/MockStaticTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest extends PowerMockTestCase {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ }
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/NotAnnotatedWithPrepareForTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/NotAnnotatedWithPrepareForTest.java
new file mode 100644
index 0000000..d6ea39f
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/NotAnnotatedWithPrepareForTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.testng.agent;
+
+import org.powermock.core.classloader.MockClassLoader;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+
+public class NotAnnotatedWithPrepareForTest {
+
+ @Test
+ public void classesNotAnnotatedWithPrepareForTestAreNotLoadedByPowerMockClassloader() throws Exception {
+ final ClassLoader classLoader = getClass().getClassLoader();
+ assertFalse(MockClassLoader.class.getName().equals(classLoader.getClass().getName()));
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PartialMockingWithBeforeClassTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PartialMockingWithBeforeClassTest.java
new file mode 100644
index 0000000..4b7bc51
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PartialMockingWithBeforeClassTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PartialMockingWithBeforeClassTest extends PowerMockTestCase {
+ private PrivateFinal tested;
+
+ @BeforeClass
+ public void setup() {
+ tested = createPartialMock(PrivateFinal.class, "sayIt");
+ }
+
+ @Test
+ public void partialMockingWithMockCreatedInBeforeClassMethod() throws Exception {
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PrivateFinalTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PrivateFinalTest.java
new file mode 100644
index 0000000..1a69f28
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/PrivateFinalTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PrivateFinalTest {
+
+ @Test
+ public void testSay() throws Exception {
+ PrivateFinal tested = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testMultiMock() throws Exception {
+ PrivateFinal tested1 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected1 = "Hello altered World";
+ expectPrivate(tested1, "sayIt", "name").andReturn(expected1);
+ replay(tested1);
+ PrivateFinal tested2 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected2 = "Hello qweqweqwe";
+ expectPrivate(tested2, "sayIt", "name").andReturn(expected2);
+ replay(tested2);
+
+ String actual1 = tested1.say("name");
+ verify(tested1);
+ Assert.assertEquals(expected1, actual1);
+ String actual2 = tested2.say("name");
+ verify(tested2);
+ Assert.assertEquals(expected2, actual2);
+ }
+
+
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SampleServletTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SampleServletTest.java
new file mode 100644
index 0000000..245e7f8
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SampleServletTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockObjectFactory;
+import org.testng.IObjectFactory;
+import org.testng.annotations.ObjectFactory;
+import org.testng.annotations.Test;
+import samples.servletmocking.SampleServlet;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at PrepareForTest(SampleServlet.class)
+public class SampleServletTest {
+
+ @Test
+ public void doGet() throws Exception {
+ SampleServlet servlet = new SampleServlet();
+
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ PrintWriter writer = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(writer);
+ writer.write("out");
+
+ replay(response, writer);
+
+ servlet.doGet(null, response);
+
+ verify(response, writer);
+ }
+
+ @ObjectFactory
+ public IObjectFactory getObjectFactory() {
+ return new PowerMockObjectFactory();
+ }
+}
diff --git a/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SystemClassUserTest.java b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SystemClassUserTest.java
new file mode 100644
index 0000000..7cbef00
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/src/test/java/samples/testng/agent/SystemClassUserTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng.agent;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+import samples.system.SystemClassUser;
+
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ * Demonstrates PowerMock's ability to mock non-final and final system classes.
+ * To mock a system class you need to prepare the calling class for testing.
+ * I.e. let's say you're testing class A which interacts with URLEncoder then
+ * you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at PrepareForTest( { SystemClassUser.class })
+public class SystemClassUserTest extends PowerMockTestCase {
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ expect(URLEncoder.encode("string", "enc")).andReturn("something");
+ replayAll();
+
+ assertEquals("something", new SystemClassUser().performEncode());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = createMock(Runtime.class);
+ Process processMock = createMock(Process.class);
+
+ expect(Runtime.getRuntime()).andReturn(runtimeMock);
+ expect(runtimeMock.exec("command")).andReturn(processMock);
+
+ replayAll();
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStaticPartial(System.class, "nanoTime");
+
+ expect(System.nanoTime()).andReturn(2L);
+
+ replayAll();
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ mockStaticPartial(System.class, "getProperty");
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+ expectLastCall().once();
+
+ replayAll();
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ expect(String.format(string, args)).andReturn(returnValue);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingStaticVoidMethodWorks() throws Exception {
+ mockStatic(Thread.class);
+
+ Thread.sleep(anyLong());
+ expectLastCall().once();
+
+ replayAll();
+
+ long startTime = System.currentTimeMillis();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.threadSleep();
+ long endTime = System.currentTimeMillis();
+ assertTrue(endTime - startTime < 5000);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInstanceMethodOfFinalSystemClassWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnection = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andStubReturn(urlConnection);
+
+ replayAll();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(urlConnection, systemClassUser.useURL(url));
+ verifyAll();
+ }
+
+ @Test
+ public void mockingURLWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnectionMock = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andReturn(urlConnectionMock);
+
+ replayAll();
+
+ assertSame(url.openConnection(), urlConnectionMock);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInetAddressWorks() throws Exception {
+ final InetAddress mock = createMock(InetAddress.class);
+ mockStatic(InetAddress.class);
+
+ expect(InetAddress.getLocalHost()).andReturn(mock);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(mock, systemClassUser.getLocalHost());
+
+ verifyAll();
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/testng-agent-test/suite.xml b/modules/module-test/easymock/testng-agent-test/suite.xml
new file mode 100644
index 0000000..99e68aa
--- /dev/null
+++ b/modules/module-test/easymock/testng-agent-test/suite.xml
@@ -0,0 +1,17 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<suite name="dgf" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
+ <test name="dgf">
+ <classes>
+ <class name="samples.testng.agent.FinalDemoTest"/>
+ <class name="samples.testng.agent.AnnotationDemoTest"/>
+ <class name="samples.testng.agent.AnnotationDemoWithBeforeMethodTest"/>
+ <class name="samples.testng.agent.PrivateFinalTest"/>
+ <class name="samples.testng.agent.MockStaticExtendsPowerMockTestCaseTest"/>
+ <class name="samples.testng.agent.PartialMockingWithBeforeClassTest"/>
+ <class name="samples.testng.agent.PrivateFinalTest"/>
+ <class name="samples.testng.agent.SystemClassUserTest" />
+ <class name="samples.testng.agent.SampleServletTest" />
+ <class name="samples.testng.agent.NotAnnotatedWithPrepareForTest" />
+ </classes>
+ </test>
+</suite>
\ No newline at end of file
diff --git a/modules/module-test/easymock/testng-test/pom.xml b/modules/module-test/easymock/testng-test/pom.xml
new file mode 100644
index 0000000..28d319e
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/pom.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-easymock-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-easymock-testng</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for EasyMock module with TestNG.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>6.9.10</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoTest.java
new file mode 100644
index 0000000..3b9eff3
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoTest.java
@@ -0,0 +1,35 @@
+package samples.testng;
+
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly in TestNG.
+ */
+ at PrepareForTest
+public class AnnotationDemoTest {
+
+ @Mock
+ private Service serviceMock;
+
+ @Test
+ public void assertInjectionWorked() throws Exception {
+ AnnotationDemo tested = new AnnotationDemo(serviceMock);
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ Assert.assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoWithBeforeMethodTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoWithBeforeMethodTest.java
new file mode 100644
index 0000000..7b9787c
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/AnnotationDemoWithBeforeMethodTest.java
@@ -0,0 +1,43 @@
+package samples.testng;
+
+import org.powermock.api.easymock.annotation.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+/**
+ * Verifies that PowerMock test listeners works correctly with before methods in
+ * TestNG.
+ */
+public class AnnotationDemoWithBeforeMethodTest {
+
+ @Mock
+ private Service serviceMock;
+
+ private AnnotationDemo tested;
+
+ @BeforeMethod
+ public void setup() {
+ tested = new AnnotationDemo(serviceMock);
+ }
+
+ @Test
+ @PrepareForTest
+ public void assertInjectionWorked() throws Exception {
+ final String expected = "mock";
+ expect(serviceMock.getServiceMessage()).andReturn(expected);
+
+ replayAll();
+
+ Assert.assertEquals(expected, tested.getServiceMessage());
+
+ verifyAll();
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/DocumentBuilderFactoryTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/DocumentBuilderFactoryTest.java
new file mode 100644
index 0000000..5ae83cc
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/DocumentBuilderFactoryTest.java
@@ -0,0 +1,13 @@
+package samples.testng;
+
+import org.testng.annotations.Test;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+public class DocumentBuilderFactoryTest {
+
+ @Test
+ public void classesNotAnnotatedWithPrepareForTestAreNotLoadedByByPowerMockCl() throws Exception {
+ DocumentBuilderFactory.newInstance();
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/FinalTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/FinalTest.java
new file mode 100644
index 0000000..220b449
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/FinalTest.java
@@ -0,0 +1,29 @@
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+import samples.finalmocking.FinalDemo;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.testng.Assert.assertEquals;
+
+ at PrepareForTest(FinalDemo.class)
+public class FinalTest extends PowerMockTestCase {
+
+ @Test
+ public void mockingFinalClassesAndMethodsWorkWithTestNGAndEasyMock() throws Exception {
+ final FinalDemo finalDemo = createMock(FinalDemo.class);
+
+ expect(finalDemo.say("something")).andReturn("something else");
+
+ replayAll();
+
+ final String actual = finalDemo.say("something");
+
+ verifyAll();
+
+ assertEquals("something else", actual);
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticExtendsPowerMockTestCaseTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticExtendsPowerMockTestCaseTest.java
new file mode 100644
index 0000000..d52b309
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticExtendsPowerMockTestCaseTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticExtendsPowerMockTestCaseTest extends PowerMockTestCase {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.say("world");
+ Assert.fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ Assert.assertEquals("\n Unexpected method call StaticService.say(\"world\"):", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ // Singleton still be mocked by now.
+ try {
+ StaticService.sayFinal("world");
+ Assert.fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ Assert.assertEquals("\n Unexpected method call StaticService.sayFinal(\"world\"):", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticTest.java
new file mode 100644
index 0000000..6fbc22e
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/MockStaticTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.verify;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+
+ @Test
+ public void testMockStatic() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.say("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.say("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ }
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ expect(StaticService.sayFinal("hello")).andReturn("Hello altered World");
+ replay(StaticService.class);
+
+ String actual = StaticService.sayFinal("hello");
+
+ verify(StaticService.class);
+ Assert.assertEquals(expected, actual);
+
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/NotAnnotatedWithPrepareForTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/NotAnnotatedWithPrepareForTest.java
new file mode 100644
index 0000000..c9c70f2
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/NotAnnotatedWithPrepareForTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.testng;
+
+import org.powermock.core.classloader.MockClassLoader;
+import org.testng.annotations.Test;
+
+import static org.testng.Assert.assertFalse;
+
+public class NotAnnotatedWithPrepareForTest {
+
+ @Test
+ public void classesNotAnnotatedWithPrepareForTestAreNotLoadedByPowerMockClassloader() throws Exception {
+ final ClassLoader classLoader = getClass().getClassLoader();
+ assertFalse(MockClassLoader.class.getName().equals(classLoader.getClass().getName()));
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PartialMockingWithBeforeClassTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PartialMockingWithBeforeClassTest.java
new file mode 100644
index 0000000..0bfbe4a
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PartialMockingWithBeforeClassTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PartialMockingWithBeforeClassTest extends PowerMockTestCase {
+ private PrivateFinal tested;
+
+ @BeforeClass
+ public void setup() {
+ tested = createPartialMock(PrivateFinal.class, "sayIt");
+ }
+
+ @Test
+ public void partialMockingWithMockCreatedInBeforeClassMethod() throws Exception {
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PrivateFinalTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PrivateFinalTest.java
new file mode 100644
index 0000000..849963a
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/PrivateFinalTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.powermock.api.easymock.PowerMock.createPartialMock;
+import static org.powermock.api.easymock.PowerMock.expectPrivate;
+
+/**
+ * Test class to demonstrate private+final method mocking.
+ */
+ at PrepareForTest(PrivateFinal.class)
+public class PrivateFinalTest {
+
+ @Test
+ public void testSay() throws Exception {
+ PrivateFinal tested = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected = "Hello altered World";
+ expectPrivate(tested, "sayIt", "name").andReturn(expected);
+ replay(tested);
+
+ String actual = tested.say("name");
+
+ verify(tested);
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testMultiMock() throws Exception {
+ PrivateFinal tested1 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected1 = "Hello altered World";
+ expectPrivate(tested1, "sayIt", "name").andReturn(expected1);
+ replay(tested1);
+ PrivateFinal tested2 = createPartialMock(PrivateFinal.class, "sayIt");
+ String expected2 = "Hello qweqweqwe";
+ expectPrivate(tested2, "sayIt", "name").andReturn(expected2);
+ replay(tested2);
+
+ String actual1 = tested1.say("name");
+ verify(tested1);
+ Assert.assertEquals(expected1, actual1);
+ String actual2 = tested2.say("name");
+ verify(tested2);
+ Assert.assertEquals(expected2, actual2);
+ }
+
+
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SampleServletTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SampleServletTest.java
new file mode 100644
index 0000000..fe50810
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SampleServletTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockObjectFactory;
+import org.testng.IObjectFactory;
+import org.testng.annotations.ObjectFactory;
+import org.testng.annotations.Test;
+import samples.servletmocking.SampleServlet;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+
+ at PrepareForTest(SampleServlet.class)
+public class SampleServletTest {
+
+ @Test
+ public void doGet() throws Exception {
+ SampleServlet servlet = new SampleServlet();
+
+ HttpServletResponse response = createMock(HttpServletResponse.class);
+ PrintWriter writer = createMock(PrintWriter.class);
+
+ expect(response.getWriter()).andReturn(writer);
+ writer.write("out");
+
+ replay(response, writer);
+
+ servlet.doGet(null, response);
+
+ verify(response, writer);
+ }
+
+ @ObjectFactory
+ public IObjectFactory getObjectFactory() {
+ return new PowerMockObjectFactory();
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/StaticInitializerExampleTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/StaticInitializerExampleTest.java
new file mode 100644
index 0000000..f75d8be
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/StaticInitializerExampleTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.testng.annotations.Test;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.reflect.Whitebox;
+import samples.staticinitializer.StaticInitializerExample;
+
+import java.util.HashSet;
+
+import static org.testng.Assert.*;
+import org.powermock.modules.testng.PowerMockTestCase;
+
+ at SuppressStaticInitializationFor("samples.staticinitializer.StaticInitializerExample")
+public class StaticInitializerExampleTest extends PowerMockTestCase {
+
+ @Test
+ public void testSupressStaticInitializer() throws Exception {
+ assertNull(StaticInitializerExample.getMySet(), "Should be null because the static initializer should be suppressed");
+ }
+
+ @Test
+ public void testSupressStaticInitializerAndSetFinalField() throws Exception {
+ assertNull(StaticInitializerExample.getMySet(), "Should be null because the static initializer should be suppressed");
+ final HashSet<String> hashSet = new HashSet<String>();
+ Whitebox.setInternalState(StaticInitializerExample.class, "mySet", hashSet);
+ assertSame(hashSet, Whitebox.getInternalState(StaticInitializerExample.class, "mySet"));
+ }
+}
diff --git a/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SystemClassUserTest.java b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SystemClassUserTest.java
new file mode 100644
index 0000000..dbcdff3
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/src/test/java/samples/testng/SystemClassUserTest.java
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.testng;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.testng.annotations.Test;
+import samples.system.SystemClassUser;
+
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.expect;
+import static org.powermock.api.easymock.PowerMock.*;
+import static org.testng.Assert.assertSame;
+import static org.testng.Assert.assertTrue;
+import static org.testng.AssertJUnit.assertEquals;
+
+/**
+ * Demonstrates PowerMock's ability to mock non-final and final system classes.
+ * To mock a system class you need to prepare the calling class for testing.
+ * I.e. let's say you're testing class A which interacts with URLEncoder then
+ * you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at PrepareForTest( { SystemClassUser.class })
+public class SystemClassUserTest {
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ expect(URLEncoder.encode("string", "enc")).andReturn("something");
+ replayAll();
+
+ assertEquals("something", new SystemClassUser().performEncode());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = createMock(Runtime.class);
+ Process processMock = createMock(Process.class);
+
+ expect(Runtime.getRuntime()).andReturn(runtimeMock);
+ expect(runtimeMock.exec("command")).andReturn(processMock);
+
+ replayAll();
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStaticPartial(System.class, "nanoTime");
+
+ expect(System.nanoTime()).andReturn(2L);
+
+ replayAll();
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+ expectLastCall().once();
+
+ replayAll();
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ mockStaticPartial(System.class, "getProperty");
+
+ expect(System.getProperty("property")).andReturn("my property");
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+
+ verifyAll();
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ expect(String.format(string, args)).andReturn(returnValue);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingStaticVoidMethodWorks() throws Exception {
+ mockStatic(Thread.class);
+
+ Thread.sleep(anyLong());
+ expectLastCall().once();
+
+ replayAll();
+
+ long startTime = System.currentTimeMillis();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.threadSleep();
+ long endTime = System.currentTimeMillis();
+ assertTrue(endTime - startTime < 5000);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInstanceMethodOfFinalSystemClassWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnection = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andStubReturn(urlConnection);
+
+ replayAll();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(urlConnection, systemClassUser.useURL(url));
+ verifyAll();
+ }
+
+ @Test
+ public void mockingURLWorks() throws Exception {
+ URL url = createMock(URL.class);
+ URLConnection urlConnectionMock = createMock(URLConnection.class);
+
+ expect(url.openConnection()).andReturn(urlConnectionMock);
+
+ replayAll();
+
+ assertSame(url.openConnection(), urlConnectionMock);
+
+ verifyAll();
+ }
+
+ @Test
+ public void mockingInetAddressWorks() throws Exception {
+ final InetAddress mock = createMock(InetAddress.class);
+ mockStatic(InetAddress.class);
+
+ expect(InetAddress.getLocalHost()).andReturn(mock);
+
+ replayAll();
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertSame(mock, systemClassUser.getLocalHost());
+
+ verifyAll();
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/easymock/testng-test/suite.xml b/modules/module-test/easymock/testng-test/suite.xml
new file mode 100644
index 0000000..3275349
--- /dev/null
+++ b/modules/module-test/easymock/testng-test/suite.xml
@@ -0,0 +1,18 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<suite name="EasyMock TestNG" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
+ <test name="General">
+ <classes>
+ <class name="samples.testng.AnnotationDemoTest"/>
+ <class name="samples.testng.AnnotationDemoWithBeforeMethodTest"/>
+ <class name="samples.testng.DocumentBuilderFactoryTest" />
+ <class name="samples.testng.FinalTest" />
+ <class name="samples.testng.MockStaticExtendsPowerMockTestCaseTest"/>
+ <class name="samples.testng.MockStaticTest"/>
+ <class name="samples.testng.NotAnnotatedWithPrepareForTest"/>
+ <class name="samples.testng.PartialMockingWithBeforeClassTest"/>
+ <class name="samples.testng.PrivateFinalTest"/>
+ <class name="samples.testng.SampleServletTest" />
+ <class name="samples.testng.SystemClassUserTest" />
+ </classes>
+ </test>
+</suite>
\ No newline at end of file
diff --git a/modules/module-test/junit4/pom.xml b/modules/module-test/junit4/pom.xml
new file mode 100644
index 0000000..6b9d4d5
--- /dev/null
+++ b/modules/module-test/junit4/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-modules-test</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-modules-test-junit4</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/modules/module-test/junit4/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java b/modules/module-test/junit4/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
new file mode 100644
index 0000000..dff1f80
--- /dev/null
+++ b/modules/module-test/junit4/src/main/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
@@ -0,0 +1,18 @@
+package org.powermock.api.extension.proxyframework;
+
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ *
+ */
+public class ProxyFrameworkImpl implements ProxyFramework {
+ @Override
+ public Class<?> getUnproxiedType(Class<?> type) {
+ return type;
+ }
+
+ @Override
+ public boolean isProxy(Class<?> type) {
+ return false;
+ }
+}
diff --git a/modules/module-test/junit4/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java b/modules/module-test/junit4/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
new file mode 100644
index 0000000..92c01fe
--- /dev/null
+++ b/modules/module-test/junit4/src/main/java/org/powermock/api/extension/reporter/MockingFrameworkReporterFactoryImpl.java
@@ -0,0 +1,21 @@
+package org.powermock.api.extension.reporter;
+
+import org.powermock.core.reporter.MockingFrameworkReporter;
+import org.powermock.core.reporter.MockingFrameworkReporterFactory;
+
+public class MockingFrameworkReporterFactoryImpl implements MockingFrameworkReporterFactory {
+ @Override
+ public MockingFrameworkReporter create() {
+ return new MockingFrameworkReporter() {
+ @Override
+ public void enable() {
+
+ }
+
+ @Override
+ public void disable() {
+
+ }
+ };
+ }
+}
diff --git a/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/GitHub352Test.java b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/GitHub352Test.java
new file mode 100644
index 0000000..d43969e
--- /dev/null
+++ b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/GitHub352Test.java
@@ -0,0 +1,49 @@
+package samples.powermockito.junit4.bugs.github352;
+
+import org.junit.Test;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Request;
+import org.junit.runner.Result;
+import org.junit.runner.Runner;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ *
+ */
+public class GitHub352Test {
+
+
+ @Test
+ public void testCountShouldBe3WhenRunWithDefaultRunner() {
+ JUnitCore jUnitCore = new JUnitCore();
+
+ Result result = jUnitCore.run(MyTest.class);
+
+ int testCount = result.getRunCount();
+ assertThat(testCount).describedAs("Test count not match to expected.", 3).isEqualTo(3);
+ }
+
+ @Test
+ public void testCountShouldBe3WhenRunWithPowerMockRunner() {
+ JUnitCore jUnitCore = new JUnitCore();
+
+ Request request = new Request() {
+ @Override
+ public Runner getRunner() {
+ try {
+ return new PowerMockRunner(MyTest.class);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+
+ Result result = jUnitCore.run(request);
+
+ int testCount = result.getRunCount();
+ assertThat(testCount).describedAs("Test count not match to expected.", 3).isEqualTo(3);
+ }
+}
diff --git a/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyAbstractTest.java b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyAbstractTest.java
new file mode 100644
index 0000000..4f5534d
--- /dev/null
+++ b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyAbstractTest.java
@@ -0,0 +1,17 @@
+package samples.powermockito.junit4.bugs.github352;
+
+import org.junit.Test;
+
+/**
+ *
+ */
+public abstract class MyAbstractTest {
+
+
+ @Test
+ public abstract void test1();
+
+ @Test
+ public abstract void test2();
+
+}
diff --git a/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyTest.java b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyTest.java
new file mode 100644
index 0000000..065d82f
--- /dev/null
+++ b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/MyTest.java
@@ -0,0 +1,27 @@
+package samples.powermockito.junit4.bugs.github352;
+
+import org.junit.Test;
+
+/**
+ *
+ */
+public class MyTest extends MyAbstractTest {
+
+ //some setup code here
+
+ @Override
+ public void test1() {
+ //some test code here
+ }
+
+ @Override
+ public void test2() {
+ //some test code here
+ }
+
+ @Test
+ public void test3() {
+ // some test code here
+ }
+
+}
diff --git a/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/package-info.java b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/package-info.java
new file mode 100644
index 0000000..4e4b33a
--- /dev/null
+++ b/modules/module-test/junit4/src/test/java/samples/powermockito/junit4/bugs/github352/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/352
+ */
+package samples.powermockito.junit4.bugs.github352;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-agent/pom.xml b/modules/module-test/mockito/junit4-agent/pom.xml
new file mode 100644
index 0000000..b5e7245
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-mockito-junit4-agent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for PowerMock Java agent with JUnit4 and Mockito
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.rules.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <argLine>
+ -javaagent:${settings.localRepository}//org/powermock/powermock-module-javaagent/${project.version}/powermock-module-javaagent-${project.version}.jar
+ </argLine>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java
new file mode 100644
index 0000000..e38d53d
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AnnotationUsageTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.agent;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.Service;
+import samples.annotationbased.AnnotationDemo;
+
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at RunWith(Parameterized.class)
+public class AnnotationUsageTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+
+ @InjectMocks
+ AnnotationDemo tested;
+
+
+ @Mock
+ Service server;
+
+
+ final String fooId;
+
+
+ public AnnotationUsageTest(String fooId) {
+ this.fooId = fooId;
+ }
+
+
+ @Parameterized.Parameters()
+ public static Iterable<Object[]> data() {
+ return Arrays.asList(new Object[][]{
+ {"1"},
+ {"2"}
+ });
+ }
+
+
+ @Before
+ public void setUp() throws Exception {
+ when(server.getServiceMessage()).thenReturn(fooId);
+ }
+
+
+ @Test
+ public void annotationsAreEnabledWhenUsingTheJUnitRule() throws Exception {
+ String serviceMessage = tested.getServiceMessage();
+ assertEquals(fooId, serviceMessage);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AssertPowerMockRuleDelagatesToOtherRulesTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AssertPowerMockRuleDelagatesToOtherRulesTest.java
new file mode 100644
index 0000000..9f69613
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/AssertPowerMockRuleDelagatesToOtherRulesTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+/**
+ * This test demonstrates that the PowerMockRule delegates to other rules.
+ */
+public class AssertPowerMockRuleDelagatesToOtherRulesTest {
+ private static final MyObject BEFORE = new MyObject();
+
+ private final List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertPowerMockRuleDelegatesToOtherRules() throws Exception {
+ assertFalse(this.getClass().getClassLoader().getClass().getName().contains(MockClassLoader.class.getName()));
+ assertEquals(1, objects.size());
+ // Not same using X-Stream
+ assertEquals(BEFORE, objects.get(0));
+ assertEquals("assertPowerMockRuleDelegatesToOtherRules", testName.getMethodName());
+ }
+
+ private class MyRule implements MethodRule {
+ @Override
+ public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ base.evaluate();
+ }
+ };
+ }
+ }
+
+ private static class MyObject {
+ private final String state = "state";
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MyObject myObject = (MyObject) o;
+
+ return state != null ? state.equals(myObject.state) : myObject.state == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return state.hashCode();
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/FinalDemoTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/FinalDemoTest.java
new file mode 100644
index 0000000..f95f617
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/FinalDemoTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito.
+ */
+ at PrepareForTest( { FinalDemo.class, PrivateFinal.class })
+public class FinalDemoTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertMockFinalWithNoExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ assertNull(tested.say(argument));
+
+ verify(tested).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+ final String expected = "Hello altered World";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.say(argument)).thenReturn(expected);
+
+ final String actual = tested.say(argument);
+
+ verify(tested).say(argument);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertFinalNativeWithExpectationsWorks() throws Exception {
+ final String expected = "Hello altered World";
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.sayFinalNative(argument)).thenReturn("Hello altered World");
+
+ String actual = tested.sayFinalNative(argument);
+
+ verify(tested).sayFinalNative(argument);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertSpyingOnFinalInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ final String argument = "PowerMock";
+ final String expected = "something";
+
+ assertEquals("Hello " + argument, spy.say(argument));
+ when(spy.say(argument)).thenReturn(expected);
+ assertEquals(expected, spy.say(argument));
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void assertSpyingOnFinalVoidInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ doThrow(new ArrayStoreException()).when(spy).finalVoidCallee();
+
+ spy.finalVoidCaller();
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorks() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ when(spy, "sayIt", isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke("sayIt", expected);
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorksWhenUsingJavaLangReflectMethod() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ final Method methodToExpect = method(PrivateFinal.class, "sayIt");
+ when(spy, methodToExpect).withArguments(isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke(methodToExpect).withArguments(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java
new file mode 100644
index 0000000..b951869
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/LargeMethodTest.java
@@ -0,0 +1,58 @@
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.largemethod.MethodExceedingJvmLimit;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at PrepareForTest(MethodExceedingJvmLimit.class)
+public class LargeMethodTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void largeMethodShouldBeOverridden() {
+ try {
+ MethodExceedingJvmLimit.init();
+ fail("Method should be overridden and exception should be thrown");
+ } catch (Exception e) {
+ assertSame(IllegalAccessException.class, e.getClass());
+ assertTrue(e.getMessage().contains("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeSuppressed() {
+ suppress(method(MethodExceedingJvmLimit.class, "init"));
+ assertNull("Suppressed method should return: null", MethodExceedingJvmLimit.init());
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeMocked() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ when(MethodExceedingJvmLimit.init()).thenReturn("ok");
+ assertEquals("Mocked method should return: ok", "ok", MethodExceedingJvmLimit.init());
+ verifyStatic();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void largeMethodShouldBeAbleToBeMockedAndThrowException() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ when(MethodExceedingJvmLimit.init()).thenThrow(new IllegalStateException());
+ MethodExceedingJvmLimit.init();
+ verifyStatic();
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MemberModificationExampleTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MemberModificationExampleTest.java
new file mode 100644
index 0000000..3403561
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MemberModificationExampleTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.staticandinstance.StaticAndInstanceDemo;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+import samples.suppresseverything.SuppressEverything;
+import samples.suppressfield.SuppressField;
+import samples.suppressmethod.SuppressMethod;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructorsDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberMatcher.everythingDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberMatcher.field;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberMatcher.methods;
+import static org.powermock.api.support.membermodification.MemberMatcher.methodsDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberModifier.replace;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * Demonstrates PowerMock's ability to modify member structures.
+ */
+ at PrepareForTest( { SuppressMethod.class, SuppressField.class, SuppressEverything.class })
+public class MemberModificationExampleTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void suppressSingleMethodExample() throws Exception {
+ suppress(method(SuppressMethod.class, "getObject"));
+
+ assertNull(new SuppressMethod().getObject());
+ }
+
+ @Test
+ public void suppressMultipleMethodsExample1() throws Exception {
+ suppress(methods(SuppressMethod.class, "getObject", "getInt"));
+
+ assertNull(new SuppressMethod().getObject());
+ assertEquals(0, new SuppressMethod().getInt());
+ }
+
+ @Test
+ public void suppressMultipleMethodsExample2() throws Exception {
+ suppress(methods(method(SuppressMethod.class, "getObject"), method(SuppressMethod.class, "getInt")));
+
+ assertNull(new SuppressMethod().getObject());
+ assertEquals(0, new SuppressMethod().getInt());
+ }
+
+ @Test
+ public void suppressAllMethodsExample() throws Exception {
+ suppress(methodsDeclaredIn(SuppressMethod.class));
+
+ final SuppressMethod tested = new SuppressMethod();
+
+ assertNull(tested.getObject());
+ assertNull(SuppressMethod.getObjectStatic());
+ assertEquals(0, tested.getByte());
+ }
+
+ @Test
+ public void suppressSingleFieldExample() throws Exception {
+ suppress(field(SuppressField.class, "domainObject"));
+
+ SuppressField tested = new SuppressField();
+ assertNull(tested.getDomainObject());
+ }
+
+ @Test
+ public void suppressConstructorExample() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+
+ assertEquals(42, tested.getNumber());
+ assertNull(tested.getMessage());
+ }
+
+ @Test
+ public void stubSingleMethodExample() throws Exception {
+ final String expectedReturnValue = "new";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expectedReturnValue);
+
+ final SuppressMethod tested = new SuppressMethod();
+ assertEquals(expectedReturnValue, tested.getObject());
+ assertEquals(expectedReturnValue, tested.getObject());
+ }
+
+ @Test
+ public void duckTypeStaticMethodExample() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "getStaticMessage"));
+
+ assertEquals(SuppressMethod.getObjectStatic(), StaticAndInstanceDemo.getStaticMessage());
+ }
+
+ @Test
+ public void whenReplacingMethodWithAMethodOfIncorrectReturnTypeThenAnIAEIsThrown() throws Exception {
+ try {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "aVoidMethod"));
+ fail("Should thow IAE");
+ } catch (Exception e) {
+ assertEquals("The replacing method (public static void samples.staticandinstance.StaticAndInstanceDemo.aVoidMethod()) needs to return java.lang.Object and not void.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void whenReplacingMethodWithAMethodOfWithIncorrectParametersThenAnIAEIsThrown() throws Exception {
+ try {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "aMethod2"));
+ fail("Should thow IAE");
+ } catch (Exception e) {
+ assertEquals("The replacing method, \"public static java.lang.Object samples.staticandinstance.StaticAndInstanceDemo.aMethod2(java.lang.String)\", needs to have the same number of parameters of the same type as as method \"public static java.lang.Object samples.suppressmethod.SuppressMethod.getObjectStatic()\".", e.getMessage());
+ }
+ }
+
+ @Test
+ public void changingReturnValueExample() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectWithArgument")).with(new ReturnValueChangingInvocationHandler());
+
+ final SuppressMethod tested = new SuppressMethod();
+
+ assertThat(tested.getObjectWithArgument("don't do anything"), is(instanceOf(Object.class)));
+ assertEquals("hello world", tested.getObjectWithArgument("make it a string"));
+ }
+
+ @Test
+ public void suppressAllConstructors() throws Exception {
+ suppress(constructorsDeclaredIn(SuppressEverything.class));
+
+ SuppressEverything suppressEverything = new SuppressEverything();
+ new SuppressEverything("test");
+
+ try {
+ suppressEverything.something();
+ fail("Should throw ISE");
+ } catch (IllegalStateException e) {
+ assertEquals("error", e.getMessage());
+ }
+ }
+
+ @Test
+ public void suppressEverythingExample() throws Exception {
+ suppress(everythingDeclaredIn(SuppressEverything.class));
+
+ SuppressEverything suppressEverything = new SuppressEverything();
+ new SuppressEverything("test");
+ suppressEverything.something();
+ suppressEverything.somethingElse();
+ }
+
+ private final class ReturnValueChangingInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object object, Method method, Object[] arguments) throws Throwable {
+ if (arguments[0].equals("make it a string")) {
+ return "hello world";
+ } else {
+ return method.invoke(object, arguments);
+ }
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockFinalUsingAnnotationsTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockFinalUsingAnnotationsTest.java
new file mode 100644
index 0000000..33ac345
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockFinalUsingAnnotationsTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.finalmocking.FinalDemo;
+
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito and PowerMock
+ * annotations.
+ */
+ at PrepareForTest(FinalDemo.class)
+ at Ignore
+public class MockFinalUsingAnnotationsTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Mock
+ private FinalDemo usingMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.mockito.MockitoAnnotations.Mock
+ private FinalDemo usingDeprecatedMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.powermock.core.classloader.annotations.Mock
+ private FinalDemo usingPowerMockMockAnnotation;
+
+ @Test
+ public void assertMockFinalWithMockitoMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingMockitoMockAnnotation.say(argument));
+
+ verify(usingMockitoMockAnnotation).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithDeprecatedMockitoMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingDeprecatedMockitoMockAnnotation.say(argument));
+
+ verify(usingDeprecatedMockitoMockAnnotation).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWhenUsingPowerMockMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingPowerMockMockAnnotation.say(argument));
+
+ verify(usingPowerMockMockAnnotation).say(argument);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticTest.java
new file mode 100644
index 0000000..97d4caf
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+
+/**
+ * Test class to demonstrate static mocking with PowerMockito.
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void testMockStaticNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticWithExpectations() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say(argument);
+ }
+
+ @Test
+ public void errorousVerificationOfStaticMethodsGivesANonMockitoStandardMessage() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ try {
+ StaticService.say(argument);
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.singleton.StaticService.say(\"hello\");\nWanted 2 times but was 1 time.", e.getMessage());
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testMockStaticThatThrowsException() throws Exception {
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenThrow(new IllegalStateException());
+
+ StaticService.say(argument);
+ }
+
+ @Test(expected = ArgumentsAreDifferent.class)
+ public void testMockStaticVerificationFails() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("Hello");
+ }
+
+ @Test
+ public void testMockStaticAtLeastOnce() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(atLeastOnce());
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticCorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ StaticService.say("hello");
+ }
+
+ @Test(expected = TooLittleActualInvocations.class)
+ public void testMockStaticIncorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(3));
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticVoidWithNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+
+ StaticService.sayHello();
+
+ verifyStatic();
+ StaticService.sayHello();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void testMockStaticVoidWhenThrowingException() throws Exception {
+ mockStatic(StaticService.class);
+
+ // Expectations
+ doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
+ StaticService.sayHello();
+
+ // Test
+ StaticService.sayHello();
+ }
+
+ @Test
+ public void testSpyOnStaticMethods() throws Exception {
+ spy(StaticService.class);
+
+ String expectedMockValue = "expected";
+ when(StaticService.say("world")).thenReturn(expectedMockValue);
+
+ assertEquals(expectedMockValue, StaticService.say("world"));
+ assertEquals("Hello world2", StaticService.say("world2"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticWithPrivateCtorTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticWithPrivateCtorTest.java
new file mode 100644
index 0000000..392f4fb
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/MockStaticWithPrivateCtorTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticWithPrivateCtor;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at PrepareForTest(StaticWithPrivateCtor.class)
+public class MockStaticWithPrivateCtorTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void canMockStaticMethodsInClassWithPrivateConstructor() throws Exception {
+ mockStatic(StaticWithPrivateCtor.class);
+ when(StaticWithPrivateCtor.staticMethod()).thenReturn("something else");
+
+ assertEquals("something else", StaticWithPrivateCtor.staticMethod());
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/PrivateInstanceMockingTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/PrivateInstanceMockingTest.java
new file mode 100644
index 0000000..ab40aeb
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/PrivateInstanceMockingTest.java
@@ -0,0 +1,116 @@
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.privateandfinal.PrivateFinal;
+import samples.privatemocking.PrivateMethodDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.never;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at PrepareForTest( { PrivateMethodDemo.class })
+public class PrivateInstanceMockingTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", 12, "test").thenReturn("another");
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ }
+
+ @Test
+ public void expectationsWorkWithArgumentMatchersWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ verifyPrivate(tested).invoke("doSayYear", 50, "Temp");
+ }
+
+ @Test
+ public void errorousVerificationOnPrivateMethodGivesFilteredErrorMessage() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ try {
+ verifyPrivate(tested, never()).invoke("doSayYear", 50, "Temp");
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.privatemocking.PrivateMethodDemo.doSayYear(\n 50,\n \"Temp\"\n);\nNever wanted but invoked .", e
+ .getMessage());
+ }
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectationsWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(Object.class)).thenThrow(new ArrayStoreException());
+
+ tested.doObjectStuff(new Object());
+ }
+
+ @Test
+ public void answersWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(String.class)).thenAnswer(new Answer<Void>() {
+ private static final long serialVersionUID = 20645008237481667L;
+
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Testing", invocation.getArguments()[0]);
+ return null;
+ }
+ });
+ tested.doObjectStuff(new Object());
+ tested.doObjectStuff("Testing");
+ }
+
+ @Test
+ public void spyingOnPrivateFinalMethodsWorksWhenClassIsNotFinal() throws Exception {
+ PrivateFinal tested = spy(new PrivateFinal());
+
+ final String name = "test";
+ tested.say(name);
+ assertEquals("Hello " + name, tested.say(name));
+
+ when(tested, "sayIt", name).thenReturn("First", "Second");
+
+ assertEquals("First", tested.say(name));
+ assertEquals("Second", tested.say(name));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/StubMethodTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/StubMethodTest.java
new file mode 100644
index 0000000..07e4578
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/StubMethodTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+import samples.suppressmethod.SuppressMethod;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+ at PrepareForTest(SuppressMethod.class)
+public class StubMethodTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void whenStubbingInstanceMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expectedValue = "Hello";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expectedValue);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expectedValue, tested.getObject());
+ assertEquals(expectedValue, tested.getObject());
+ }
+
+ @Test
+ public void whenStubbingStaticMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expectedValue = "Hello";
+ stub(method(SuppressMethod.class, "getObjectStatic")).toReturn(expectedValue);
+
+ assertEquals(expectedValue, SuppressMethod.getObjectStatic());
+ assertEquals(expectedValue, SuppressMethod.getObjectStatic());
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodWithPrimiteValueTheMethodReturnsTheStubbedValue() throws Exception {
+ float expectedValue = 4;
+ stub(method(SuppressMethod.class, "getFloat")).toReturn(expectedValue);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expectedValue, tested.getFloat(), 0.0f);
+ assertEquals(expectedValue, tested.getFloat(), 0.0f);
+ }
+
+ @Test(expected = TooManyMethodsFoundException.class)
+ public void whenSeveralMethodsFoundThenTooManyMethodsFoundExceptionIsThrown() throws Exception {
+ stub(method(SuppressMethod.class, "sameName"));
+ }
+
+ @Test(expected = MethodNotFoundException.class)
+ public void whenNoMethodsFoundThenMethodNotFoundExceptionIsThrown() throws Exception {
+ stub(method(SuppressMethod.class, "notFound"));
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodByPassingTheMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expected = "Hello";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expected);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ assertEquals(expected, tested.getObject());
+ assertEquals(expected, tested.getObject());
+ }
+
+ @Test
+ public void whenStubbingStaticMethodByPassingTheMethodTheMethodReturnsTheStubbedValue() throws Exception {
+ String expected = "Hello";
+ stub(method(SuppressMethod.class, "getObjectStatic")).toReturn(expected);
+
+ assertEquals(expected, SuppressMethod.getObjectStatic());
+ assertEquals(expected, SuppressMethod.getObjectStatic());
+ }
+
+ @Test(expected = ClassCastException.class)
+ public void whenStubbingInstanceMethodWithWrongReturnTypeThenClasscastExceptionIsThrown() throws Exception {
+ String illegalReturnType = "Hello";
+ stub(method(SuppressMethod.class, "getFloat")).toReturn(illegalReturnType);
+ SuppressMethod tested = new SuppressMethod();
+ tested.getFloat();
+ }
+
+ @Test
+ public void whenStubbingInstanceMethodToThrowExceptionTheMethodThrowsTheStubbedException() throws Exception {
+ Exception expected = new Exception("message");
+ stub(method(SuppressMethod.class, "getObject")).toThrow(expected);
+
+ SuppressMethod tested = new SuppressMethod();
+
+ try {
+ tested.getObject();
+ fail();
+ } catch (Exception e) {
+ assertEquals("message", e.getMessage());
+ }
+ }
+
+ @Test
+ public void whenStubbingStaticMethodToThrowExceptionTheMethodThrowsTheStubbedException() throws Exception {
+ Exception expected = new Exception("message");
+ stub(method(SuppressMethod.class, "getObjectStatic")).toThrow(expected);
+ try {
+ SuppressMethod.getObjectStatic();
+ fail();
+ } catch (Exception e) {
+ assertEquals("message", e.getMessage());
+ }
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorDemoTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorDemoTest.java
new file mode 100644
index 0000000..f9300c0
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorDemoTest.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.suppressconstructor.SuppressConstructorDemo;
+import samples.suppressconstructor.SuppressConstructorSubclassDemo;
+
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * This test demonstrates how to tell PowerMock to avoid executing constructor
+ * code for a certain class. This is crucial in certain tests where the
+ * constructor or a subclass's constructor performs operations that are of no
+ * concern to the unit test of the actual class or if the constructor performs
+ * operations, such as getting services from a runtime environment that has not
+ * been initialized. In normal situations you're forced to create an integration
+ * or function test for the class instead (and thus the runtime environment is
+ * available). This is not particularly good when it comes to testing method
+ * logic.
+ */
+ at PrepareForTest(SuppressConstructorDemo.class)
+public class SuppressConstructorDemoTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ /**
+ * This test makes sure that the real constructor has never been called.
+ */
+ @Test
+ public void testSuppressConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorDemo.class));
+ final SuppressConstructorDemo tested = new SuppressConstructorDemo("a message");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+
+ /**
+ * This test makes sure that the real parent constructor has never been
+ * called.
+ */
+ @Test
+ @Ignore("Doesn't work when using the Java agent")
+ public void testSuppressParentConstructor() throws Exception {
+ suppress(constructor(SuppressConstructorSubclassDemo.class));
+ final SuppressConstructorDemo tested = new SuppressConstructorDemo("a message");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorHierarchyDemoTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorHierarchyDemoTest.java
new file mode 100644
index 0000000..e9045da
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SuppressConstructorHierarchyDemoTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.suppressconstructor.InvokeConstructor;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at PrepareForTest(SuppressConstructorHierarchy.class)
+public class SuppressConstructorHierarchyDemoTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ @Ignore("Doesn't work from the java agent")
+ public void testSuppressConstructorHierarchy() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ final String message = new InvokeConstructor().doStuff("qwe");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code. Message was \"" + message + "\".",
+ message);
+ }
+
+ @Test
+ @PrepareForTest
+ public void testNotSuppressConstructorWithoutByteCodeManipulation() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNotSuppressConstructorWithByteCodeManipulation() throws Exception {
+ try {
+ new SuppressConstructorHierarchy("message");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException e) {
+ assertEquals("This should be suppressed!!", e.getMessage());
+ }
+ }
+
+ /**
+ * This simple test demonstrate that it's possible to continue execution
+ * with the default <code>PrepareForTest</code> settings (i.e. using a
+ * byte-code manipulated version of the SuppressConstructorHierarchyDemo
+ * class).
+ */
+ @Test
+ public void testSuppressConstructorHierarchyAgain() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+ assertEquals(42, tested.getNumber());
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SystemClassUserTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SystemClassUserTest.java
new file mode 100644
index 0000000..b00267c
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/SystemClassUserTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.system.SystemClassUser;
+
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at SuppressWarnings("MalformedFormatString")
+ at PrepareForTest( { SystemClassUser.class })
+public class SystemClassUserTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ when(URLEncoder.encode("string", "enc")).thenReturn("something");
+
+ assertEquals("something", new SystemClassUser().performEncode());
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = mock(Runtime.class);
+ Process processMock = mock(Process.class);
+
+ when(Runtime.getRuntime()).thenReturn(runtimeMock);
+ when(runtimeMock.exec("command")).thenReturn(processMock);
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ spy(System.class);
+
+ when(System.nanoTime()).thenReturn(2L);
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyStatic(times(2));
+ Collections.shuffle(list);
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ spy(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ when(String.format(string, args)).thenReturn(returnValue);
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/WhenNewTest.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/WhenNewTest.java
new file mode 100644
index 0000000..b205959
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/WhenNewTest.java
@@ -0,0 +1,600 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.agent;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate new instance mocking using whenConstructionOf(..).
+ *
+ */
+ at SuppressWarnings("PrimitiveArrayArgumentToVariableArgMethod")
+ at PrepareForTest({ MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class WhenNewTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new IOException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage()).thenReturn("Hello altered World");
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock).getMessage();
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage("test")).thenReturn("Hello altered World");
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock).getMessage("test");
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ doNothing().when(myClassMock).voidMethod();
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock).voidMethod();
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new RuntimeException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+ try {
+ verifyNew(MyClass.class, times(1)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 1 time but was 3 times.", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ try {
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 2 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ //
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ whenNew(DataInputStream.class).withArguments(null).thenThrow(new RuntimeException("error"));
+
+ InputStream stream = tested.alternativePath();
+
+ verifyNew(DataInputStream.class).withArguments(null);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.",
+ stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withParameterTypes(Service.class, int.class)
+ .withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithConstructorUsingParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class, Service.class, int.class)).withArguments(serviceMock,
+ numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewUsingConstructorWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class)).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllMessages()).thenReturn(new String[] { firstString, secondString });
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ whenNew(VarArgsConstructorDemo.class).withArguments(object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName()
+ + "' with parameter types: [ " + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = mock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllServices()).thenReturn(new Service[] { serviceMock });
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull()
+ throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ /*
+ * Should throw NPE because the default behavior of Mockito when a
+ * something isn't expected is to return a default value. In this case
+ * whenConstructionOf
+ * (ExpectNewServiceUser.class).withArguments(serviceMock,
+ * numberOfTimes) is the wrong expectation and thus null is returned
+ * from the substitute mock which is the correct behavior.
+ */
+ fail("Should throw NPE!");
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.makeDate();
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "Wanted but not invoked samples.newmocking.MyClass();\nActually, there were zero interactions with this mock.",
+ e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/Github512Test.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/Github512Test.java
new file mode 100644
index 0000000..9163ecf
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/Github512Test.java
@@ -0,0 +1,26 @@
+package samples.powermockito.junit4.agent.github512;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.method;
+import static org.powermock.api.mockito.PowerMockito.suppress;
+
+ at PowerMockIgnore("org.assertj.*")
+public class Github512Test {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ @PrepareForTest(StaticService.class)
+ public void shouldSuppressMethodWithPrepareForTestOnMethod() {
+ suppress(method(StaticService.class, "calculate"));
+ assertThat(StaticService.calculate(1, 5)).isEqualTo(0);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/package-info.java b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/package-info.java
new file mode 100644
index 0000000..1e1e705
--- /dev/null
+++ b/modules/module-test/mockito/junit4-agent/src/test/java/samples/powermockito/junit4/agent/github512/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/512
+ */
+package samples.powermockito.junit4.agent.github512;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-delegate/pom.xml b/modules/module-test/mockito/junit4-delegate/pom.xml
new file mode 100644
index 0000000..a1f8639
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-mockito-junit4-delegate</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for PowerMock JUnit4 runner-delegate and Mockito
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/EnclosedTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/EnclosedTest.java
new file mode 100644
index 0000000..39fb44d
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/EnclosedTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * Demonstrates how PowerMockRunner with annotation PowerMockRunnerDelegate can
+ * provide PowerMock features to yet-another JUnit runner.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Enclosed.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class EnclosedTest {
+
+ private static final String stubbedReturnValue
+ = "Stubbed return-value from " + EnclosedTest.class;
+
+ public static class NoStubbing {
+
+ @Test
+ public void noStubbing() {
+ assertThat("Original return-value of #getStaticMessage()",
+ StaticAndInstanceDemo.getStaticMessage(),
+ not(equalTo(stubbedReturnValue)));
+ }
+ }
+
+ public static class StubbedStaticReturnValue {
+
+ @Test
+ public void stubbedStaticReturnValue() {
+ mockStatic(StaticAndInstanceDemo.class);
+ when(StaticAndInstanceDemo.getStaticMessage())
+ .thenReturn(stubbedReturnValue);
+ assertThat("Stubbed return-value of #getStaticMessag()",
+ StaticAndInstanceDemo.getStaticMessage(),
+ equalTo(stubbedReturnValue));
+ verifyStatic();
+ StaticAndInstanceDemo.getStaticMessage();
+ verifyNoMoreInteractions(StaticAndInstanceDemo.class);
+ }
+ }
+
+ public static class WhenStubbingIsOver {
+
+ @Test
+ public void whenStubbingIsOver() {
+ assertThat("Back to original return-value of #getStaticMessage()",
+ StaticAndInstanceDemo.getStaticMessage(),
+ not(equalTo(stubbedReturnValue)));
+ }
+ }
+
+ public static class SubClass extends StubbedStaticReturnValue {}
+
+ public static class SubClassWithExtraNonPublicConstructors
+ extends StubbedStaticReturnValue {
+ public SubClassWithExtraNonPublicConstructors() {}
+ private SubClassWithExtraNonPublicConstructors(boolean arg) {}
+ protected SubClassWithExtraNonPublicConstructors(String arg) {}
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/MultipleConstructorsTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/MultipleConstructorsTest.java
new file mode 100644
index 0000000..6535ea1
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/MultipleConstructorsTest.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+/**
+ * Verifies that an additional non-public constructor does not break the test-run.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate
+public class MultipleConstructorsTest {
+
+ public MultipleConstructorsTest() {
+ }
+
+ protected MultipleConstructorsTest(String s) {
+ }
+
+ @Test
+ public void dummyTest() {}
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SelfieTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SelfieTest.java
new file mode 100644
index 0000000..0145fd1
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SelfieTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.hamcrest.Matcher;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runner.Runner;
+import org.junit.runner.notification.Failure;
+import org.junit.runner.notification.RunNotifier;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.not;
+import static org.junit.runner.Description.createTestDescription;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * Demonstrates how PowerMockRunner with annotation PowerMockRunnerDelegate can
+ * provide a low-level JUnit (in this case a self-contained "selfie" test)
+ * with some PowerMock abilities.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(SelfieTest.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class SelfieTest extends Runner {
+
+ private static final String stubbedReturnValue
+ = "Stubbed return-value from " + SelfieTest.class;
+
+ private static final Description first = createTestDescription(
+ SelfieTest.class, "No Stubbing");
+ private static final Description second = createTestDescription(
+ SelfieTest.class, "Stubbed Static Return-Value");
+
+ /**
+ * Mandatory Runner constructor
+ */
+ public SelfieTest(Class<SelfieTest> ignore) {
+ }
+
+ @Override
+ public Description getDescription() {
+ Description desc = Description
+ .createSuiteDescription(SelfieTest.class);
+ desc.addChild(first);
+ desc.addChild(second);
+ return desc;
+ }
+
+ @Override
+ public void run(RunNotifier notifier) {
+ assert_getStaticMessage(notifier, first,
+ not(equalTo(stubbedReturnValue)));
+ mockStatic(StaticAndInstanceDemo.class);
+ when(StaticAndInstanceDemo.getStaticMessage())
+ .thenReturn(stubbedReturnValue);
+ assert_getStaticMessage(notifier, second, equalTo(stubbedReturnValue));
+ }
+
+ void assert_getStaticMessage(RunNotifier notifier, Description currentTest,
+ Matcher<? super String> getStaticMessageExpectation) {
+ notifier.fireTestStarted(currentTest);
+ try {
+ String staticMessage = StaticAndInstanceDemo.getStaticMessage();
+ if (getStaticMessageExpectation.matches(staticMessage)) {
+ notifier.fireTestFinished(currentTest);
+ } else {
+ notifier.fireTestFailure(new Failure(currentTest, new AssertionError(
+ "Unexpected #getStaticMessage() return-value: "
+ + staticMessage)));
+ }
+ } catch (Exception ex) {
+ notifier.fireTestFailure(new Failure(currentTest, ex));
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SubclassDelegateTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SubclassDelegateTest.java
new file mode 100644
index 0000000..03aeb38
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SubclassDelegateTest.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+
+/**
+ * To verify that annotation {@link PowerMockRunnerDelegate} works OK when the
+ * test-class has a super-class that will be loaded from the same class-loader.
+ * (This used to make JUnit's default runner fail with
+ * java.lang.IllegalArgumentException: Test class can only have one constructor
+ * during initialization.)
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate
+public class SubclassDelegateTest extends SuperClass {
+
+ @Test
+ public void test() {}
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuperClass.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuperClass.java
new file mode 100644
index 0000000..daee7b3
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuperClass.java
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2015 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+class SuperClass {}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethod.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethod.java
new file mode 100644
index 0000000..1d22108
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethod.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import samples.suppressmethod.SuppressMethod;
+
+public enum SuppressedMethod {
+
+ getObject {
+ @Override
+ public Object invokeOn(SuppressMethod tested) {
+ return tested.getObject();
+ }
+ },
+ getObjectStatic {
+ @Override
+ public Object invokeOn(SuppressMethod tested) {
+ return SuppressMethod.getObjectStatic();
+ }
+ },
+ getFloat {
+ @Override
+ public Object invokeOn(SuppressMethod tested) {
+ return tested.getFloat();
+ }
+ };
+
+ public abstract Object invokeOn(SuppressMethod tested);
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethodStubbing.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethodStubbing.java
new file mode 100644
index 0000000..b061596
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SuppressedMethodStubbing.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import java.util.concurrent.Callable;
+import org.powermock.api.support.membermodification.strategy.MethodStubStrategy;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public enum SuppressedMethodStubbing {
+
+ Hello("Hello"),
+ float_4(4.0F),
+ exception(new Exception("message")) {
+ @Override
+ public <T> void enforceOn(MethodStubStrategy<T> stub) {
+ stub.toThrow((Exception) value);
+ }
+
+ @Override
+ public void verify(final Callable<?> invocation) throws Exception {
+ super.verify(new Callable<Exception>() {
+ @Override
+ public Exception call() {
+ try {
+ invocation.call();
+ fail("Expected exception: " + value);
+ return null;
+ } catch (Exception actualException) {
+ return actualException;
+ }
+ }
+ });
+ }
+
+ @Override
+ public String toString() {
+ return "throws Exception";
+ }
+ };
+
+ final Object value;
+
+ private SuppressedMethodStubbing(Object value) {
+ this.value = value;
+ }
+
+ public <T> void enforceOn(MethodStubStrategy<T> stub) {
+ stub.toReturn((T) value);
+ }
+
+ public void verify(Callable<?> invocation) throws Exception {
+ assertEquals(value, invocation.call());
+ }
+
+ @Override
+ public String toString() {
+ return "returns " + value;
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserCases.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserCases.java
new file mode 100644
index 0000000..f33b6e0
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserCases.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import samples.system.SystemClassUser;
+
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at PrepareForTest({SystemClassUser.class})
+public class SystemClassUserCases {
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ when(URLEncoder.encode("string", "enc")).thenReturn("something");
+
+ assertEquals("something", new SystemClassUser().performEncode());
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = mock(Runtime.class);
+ Process processMock = mock(Process.class);
+
+ when(Runtime.getRuntime()).thenReturn(runtimeMock);
+ when(runtimeMock.exec("command")).thenReturn(processMock);
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ spy(System.class);
+
+ when(System.nanoTime()).thenReturn(2L);
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyStatic(times(2));
+ Collections.shuffle(list);
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ spy(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ when(String.format(string, args)).thenReturn(returnValue);
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserMethod.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserMethod.java
new file mode 100644
index 0000000..5ccad4c
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/SystemClassUserMethod.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+
+public class SystemClassUserMethod {
+
+ private final Method method;
+
+ public SystemClassUserMethod(Method method) {
+ this.method = method;
+ }
+
+ public static SystemClassUserMethod[] values() {
+ Method[] methods = SystemClassUserCases.class.getDeclaredMethods();
+ List<SystemClassUserMethod> values =
+ new ArrayList<SystemClassUserMethod>(methods.length);
+ for (Method m : methods) {
+ if (m.isAnnotationPresent(Test.class)) {
+ values.add(new SystemClassUserMethod(m));
+ }
+ }
+ return values.toArray(new SystemClassUserMethod[values.size()]);
+ }
+
+ @Override
+ public String toString() {
+ return method.getName();
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCaseMethod.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCaseMethod.java
new file mode 100644
index 0000000..fbcc445
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCaseMethod.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+
+public class WhenNewCaseMethod {
+
+ final Method testMethod;
+
+ public WhenNewCaseMethod(Method testMethod) {
+ this.testMethod = testMethod;
+ }
+
+ @Override
+ public String toString() {
+ return testMethod.getName();
+ }
+
+ public void runTest() throws Throwable {
+ try {
+ testMethod.invoke(new WhenNewCases());
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+
+ public boolean nullPointerIsExpected() {
+ return NullPointerException.class
+ == testMethod.getAnnotation(Test.class).expected();
+ }
+
+ public static WhenNewCaseMethod[] values() {
+ Method[] methods = WhenNewCases.class.getDeclaredMethods();
+ List<WhenNewCaseMethod> values
+ = new ArrayList<WhenNewCaseMethod>(methods.length);
+ for (Method m : methods) {
+ if (m.isAnnotationPresent(Test.class)) {
+ values.add(new WhenNewCaseMethod(m));
+ }
+ }
+ return values.toArray(new WhenNewCaseMethod[values.size()]);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCases.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCases.java
new file mode 100644
index 0000000..d3ea519
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/WhenNewCases.java
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate;
+
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate new instance mocking using whenConstructionOf(..).
+ *
+ */
+ at PrepareForTest({MyClass.class, ExpectNewDemo.class, DataInputStream.class})
+public class WhenNewCases {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new IOException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage()).thenReturn("Hello altered World");
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock).getMessage();
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage("test")).thenReturn("Hello altered World");
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock).getMessage("test");
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ doNothing().when(myClassMock).voidMethod();
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock).voidMethod();
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new RuntimeException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+ try {
+ verifyNew(MyClass.class, times(1)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 1 time but was 3 times.", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ try {
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 2 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ //
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ whenNew(DataInputStream.class).withArguments(null).thenThrow(new RuntimeException("error"));
+
+ InputStream stream = tested.alternativePath();
+
+ verifyNew(DataInputStream.class).withArguments(null);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.",
+ stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withParameterTypes(Service.class, int.class)
+ .withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithConstructorUsingParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class, Service.class, int.class)).withArguments(serviceMock,
+ numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewUsingConstructorWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class)).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllMessages()).thenReturn(new String[]{firstString, secondString});
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ whenNew(VarArgsConstructorDemo.class).withArguments(object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName()
+ + "' with parameter types: [ " + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = mock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllServices()).thenReturn(new Service[]{serviceMock});
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[]{42};
+ final byte[] byteArrayTwo = new byte[]{17};
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayOne});
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[]{42};
+ final byte[] byteArrayTwo = new byte[]{17};
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayOne});
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[]{17};
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayTwo});
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[]{42};
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayOne});
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull()
+ throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[]{42};
+ final byte[] byteArrayThree = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayTwo});
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][]{byteArrayTwo});
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ /*
+ * Should throw NPE because the default behavior of Mockito when a
+ * something isn't expected is to return a default value. In this case
+ * whenConstructionOf
+ * (ExpectNewServiceUser.class).withArguments(serviceMock,
+ * numberOfTimes) is the wrong expectation and thus null is returned
+ * from the substitute mock which is the correct behavior.
+ */
+ fail("Should throw NPE!");
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.makeDate();
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "Wanted but not invoked samples.newmocking.MyClass();\nActually, there were zero interactions with this mock.",
+ e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/FinalDemoTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/FinalDemoTest.java
new file mode 100644
index 0000000..6bf3754
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/FinalDemoTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2011-2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest({FinalDemo.class, PrivateFinal.class})
+public class FinalDemoTest {
+
+ @Parameterized.Parameter(0)
+ public String expected;
+
+ @Parameterized.Parameters(name = "expected={0}")
+ public static Collection<?> expections() {
+ return java.util.Arrays.asList(new Object[][]{
+ {"Hello altered World"}, {"something"}, {"test"}
+ });
+ }
+
+ @Test
+ public void assertMockFinalWithNoExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ assertNull(tested.say(argument));
+
+ verify(tested).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.say(argument)).thenReturn(expected);
+
+ final String actual = "" + tested.say(argument);
+
+ verify(tested).say(argument);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertFinalNativeWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.sayFinalNative(argument)).thenReturn(expected);
+
+ String actual = "" + tested.sayFinalNative(argument);
+
+ verify(tested).sayFinalNative(argument);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertSpyingOnFinalInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ final String argument = "PowerMock";
+
+ assertEquals("Hello " + argument, spy.say(argument));
+ when(spy.say(argument)).thenReturn(expected);
+ assertEquals(expected, "" + spy.say(argument));
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void assertSpyingOnFinalVoidInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ doThrow(new ArrayStoreException()).when(spy).finalVoidCallee();
+
+ spy.finalVoidCaller();
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorks() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ when(spy, "sayIt", isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, "" + spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke("sayIt", expected);
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorksWhenUsingJavaLangReflectMethod() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ final Method methodToExpect = method(PrivateFinal.class, "sayIt");
+ when(spy, methodToExpect).withArguments(isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, "" + spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke(methodToExpect).withArguments(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/MockFinalUsingAnnotationsTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/MockFinalUsingAnnotationsTest.java
new file mode 100644
index 0000000..0cc98b5
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/MockFinalUsingAnnotationsTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import org.powermock.reflect.Whitebox;
+import samples.finalmocking.FinalDemo;
+
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito and PowerMock
+ * annotations.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest(FinalDemo.class)
+public class MockFinalUsingAnnotationsTest {
+
+ @Mock
+ private FinalDemo usingMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.mockito.MockitoAnnotations.Mock
+ private FinalDemo usingDeprecatedMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.powermock.core.classloader.annotations.Mock
+ private FinalDemo usingPowerMockMockAnnotation;
+
+ @Parameterized.Parameter(0)
+ public MockField field2test;
+
+ @Test
+ public void testMockFinal() throws Exception {
+ final String argument = "hello";
+ System.out.println(field2test);
+ FinalDemo mockedFinal = field2test.inTest(this);
+ assertNull(mockedFinal.say(argument));
+ verify(mockedFinal).say(argument);
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> vals() {
+ MockField[] mockFields = MockField.values();
+ List<Object[]> vals = new ArrayList<Object[]>(mockFields.length);
+ for (MockField each : mockFields) {
+ vals.add(new Object[]{each});
+ }
+ return vals;
+ }
+
+ enum MockField {
+
+ usingMockitoMockAnnotation,
+ usingDeprecatedMockitoMockAnnotation,
+ usingPowerMockMockAnnotation;
+
+ <T> T inTest(Object test) {
+ try {
+ return (T) Whitebox.getInternalState(test, name());
+ } catch (Exception ex) {
+ throw new Error(ex);
+ }
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/StubMethodTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/StubMethodTest.java
new file mode 100644
index 0000000..6824163
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/StubMethodTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.Callable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import powermock.modules.test.mockito.junit4.delegate.SuppressedMethod;
+import powermock.modules.test.mockito.junit4.delegate.SuppressedMethodStubbing;
+import samples.suppressmethod.SuppressMethod;
+
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+import static powermock.modules.test.mockito.junit4.delegate.SuppressedMethod.*;
+import static powermock.modules.test.mockito.junit4.delegate.SuppressedMethodStubbing.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest(SuppressMethod.class)
+public class StubMethodTest {
+
+ @Parameterized.Parameter(0)
+ public SuppressedMethod method;
+
+ @Parameterized.Parameter(1)
+ public SuppressedMethodStubbing stubbing;
+
+ @Test
+ public void test() throws Exception {
+ stubbing.enforceOn(stub(method(SuppressMethod.class, method.name())));
+
+ final SuppressMethod tested = new SuppressMethod();
+ Callable<?> methodInvocation = new Callable<Object>() {
+ @Override
+ public Object call() {
+ return method.invokeOn(tested);
+ }
+ };
+
+ stubbing.verify(methodInvocation);
+ stubbing.verify(methodInvocation);
+ stubbing.verify(methodInvocation);
+ }
+
+ @Parameterized.Parameters(name = " {0} {1}")
+ public static List<?> paramValues() {
+ return Arrays.asList(new Object[][]{
+ {getObject, Hello},
+ {getObject, float_4},
+ {getObject, exception},
+ {getObjectStatic, Hello},
+ {getObjectStatic, float_4},
+ {getObjectStatic, exception},
+ // {getFloat, Hello}, //Incompatible return-type
+ {getFloat, float_4},
+ {getFloat, exception},});
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorDemoTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorDemoTest.java
new file mode 100644
index 0000000..a29b0b8
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorDemoTest.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.suppressconstructor.SuppressConstructorDemo;
+import samples.suppressconstructor.SuppressConstructorSubclassDemo;
+
+import static org.junit.Assert.assertNull;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+/**
+ * This test demonstrates how to tell PowerMock to avoid executing constructor
+ * code for a certain class. This is crucial in certain tests where the
+ * constructor or a subclass's constructor performs operations that are of no
+ * concern to the unit test of the actual class or if the constructor performs
+ * operations, such as getting services from a runtime environment that has not
+ * been initialized. In normal situations you're forced to create an integration
+ * or function test for the class instead (and thus the runtime environment is
+ * available). This is not particularly good when it comes to testing method
+ * logic.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest(SuppressConstructorDemo.class)
+public class SuppressConstructorDemoTest {
+
+ final Class<? super SuppressConstructorDemo> constructor2suppress;
+
+ public SuppressConstructorDemoTest(
+ Class<? super SuppressConstructorDemo> constructor2suppress) {
+ this.constructor2suppress = constructor2suppress;
+ }
+
+ /**
+ * This test makes sure that the real constructor has never been called.
+ */
+ @Test
+ public void testSuppressConstructor() throws Exception {
+ suppress(constructor(constructor2suppress));
+ final SuppressConstructorDemo tested = new SuppressConstructorDemo("a message");
+ assertNull("Message should have been null since we're skipping the execution of the constructor code.", tested.getMessage());
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> classesWithConstructor2suppress() {
+ List<?> constructorClasses = Arrays.asList(new Object[][]{
+ {SuppressConstructorSubclassDemo.class},
+ {SuppressConstructorDemo.class}
+ });
+ Collections.shuffle(constructorClasses);
+ return constructorClasses;
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorHierarchyDemoTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorHierarchyDemoTest.java
new file mode 100644
index 0000000..4d190c5
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SuppressConstructorHierarchyDemoTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.util.Arrays;
+import java.util.List;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.suppressconstructor.InvokeConstructor;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+
+import static org.junit.Assert.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest(SuppressConstructorHierarchy.class)
+public class SuppressConstructorHierarchyDemoTest {
+
+ @Parameterized.Parameter
+ public boolean suppress;
+
+ @Parameterized.Parameters(name = "suppress={0}")
+ public static List<?> false_or_true() {
+ return Arrays.asList(new Object[][]{{false}, {true}});
+ }
+
+ @Before
+ public void suppressOnDemand() {
+ if (suppress) {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ }
+ }
+
+ @Test
+ public void directConstructorUsage() throws Exception {
+ System.out.println("ClassLoader: " + getClass().getClassLoader());
+ try {
+ SuppressConstructorHierarchy tested
+ = new SuppressConstructorHierarchy("message");
+ if (suppress) {
+ assertNull(
+ "Message should have been null since we're skipping the execution of the constructor code. Message was \"message\".",
+ tested.getMessage());
+ assertEquals("getNumber() value", 42, tested.getNumber());
+ } else {
+ fail("Expected RuntimeException");
+ }
+ } catch (RuntimeException ex) {
+ if (suppress) {
+ throw ex;
+ } else {
+ assertEquals("This should be suppressed!!", ex.getMessage());
+ }
+ }
+ }
+
+ @Test
+ public void useConstructorInvoker() throws Exception {
+ System.out.println("ClassLoader: " + getClass().getClassLoader());
+ try {
+ final String message = new InvokeConstructor().doStuff("qwe");
+ if (suppress) {
+ assertNull("Message should have been null since we're skipping the execution of the constructor code. Message was \"" + message + "\".",
+ message);
+ } else {
+ fail("Expected RuntimeException");
+ }
+ } catch (RuntimeException ex) {
+ if (suppress) {
+ throw ex;
+ } else {
+ assertEquals("This should be suppressed!!", ex.getMessage());
+ }
+ }
+ }
+
+ @Test
+ @PrepareForTest
+ public void suppressWithoutByteCodeManipulation() throws Exception {
+ System.out.println("ClassLoader: " + getClass().getClassLoader());
+ try {
+ new InvokeConstructor().doStuff("qwe");
+ fail("Should throw RuntimeException since we're running this test with a new class loader!");
+ } catch (RuntimeException ex) {
+ assertEquals("This should be suppressed!!", ex.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SupressMethodExampleTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SupressMethodExampleTest.java
new file mode 100644
index 0000000..802771d
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SupressMethodExampleTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2011-2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.hamcrest.Matcher;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+import samples.suppresseverything.SuppressEverything;
+import samples.suppressfield.SuppressField;
+import samples.suppressmethod.SuppressMethod;
+import samples.suppressfield.DomainObject;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.*;
+import static org.powermock.api.support.membermodification.MemberModifier.*;
+
+/**
+ * Demonstrates PowerMock's ability to modify member structures.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest({SuppressMethod.class, SuppressField.class, SuppressEverything.class})
+public class SupressMethodExampleTest {
+
+ enum GetObjectSuppression {
+
+ DONT_SUPPRESS(SuppressMethod.OBJECT),
+ SUPPRESS(null) {
+ @Override
+ void doIt() {
+ suppress(method(SuppressMethod.class, "getObject"));
+ }
+ };
+
+ final Object expectedReturnValue;
+
+ GetObjectSuppression(Object expectedReturnValue) {
+ this.expectedReturnValue = expectedReturnValue;
+ }
+
+ void doIt() {
+ }
+ }
+
+ enum GetIntSuppression {
+
+ DONT_SUPPRESS(Integer.MAX_VALUE),
+ SUPPRESS(0) {
+ @Override
+ void doIt() {
+ suppress(method(SuppressMethod.class, "getInt"));
+ }
+ };
+
+ final int expectedReturnValue;
+
+ GetIntSuppression(int expectedReturnValue) {
+ this.expectedReturnValue = expectedReturnValue;
+ }
+
+ void doIt() {
+ }
+ }
+
+ enum FieldSuppression {
+
+ DONT_SUPPRESS(instanceOf(DomainObject.class)),
+ SUPPRESS(nullValue()) {
+ @Override
+ void doIt() {
+ suppress(field(SuppressField.class, "domainObject"));
+ }
+ };
+
+ final Matcher<? super DomainObject> expectation;
+
+ private FieldSuppression(Matcher<? super DomainObject> expectation) {
+ this.expectation = expectation;
+ }
+
+ void doIt() {
+ }
+ }
+
+ final GetObjectSuppression getObjectSuppression;
+ final GetIntSuppression getIntSuppression;
+ final FieldSuppression fieldSuppression;
+ final boolean suppressConstructor;
+
+ @Rule
+ public final ExpectedException expectedException = ExpectedException.none();
+
+ public SupressMethodExampleTest(
+ GetObjectSuppression getObjectSuppression,
+ GetIntSuppression getIntSuppression,
+ FieldSuppression fieldSuppression,
+ Boolean suppressConstructor) {
+ this.getObjectSuppression = getObjectSuppression;
+ this.getIntSuppression = getIntSuppression;
+ this.fieldSuppression = fieldSuppression;
+ this.suppressConstructor = suppressConstructor;
+ }
+
+ @Parameterized.Parameters(name = "getObject={0} getInt={1} field={2} suppressConstructor={3}")
+ public static Collection<?> suppressionParamValues() {
+ return Arrays.asList(new Object[][]{
+ {GetObjectSuppression.DONT_SUPPRESS, GetIntSuppression.DONT_SUPPRESS,
+ FieldSuppression.DONT_SUPPRESS, false},
+ {GetObjectSuppression.DONT_SUPPRESS, GetIntSuppression.SUPPRESS,
+ FieldSuppression.DONT_SUPPRESS, false},
+ {GetObjectSuppression.SUPPRESS, GetIntSuppression.DONT_SUPPRESS,
+ FieldSuppression.DONT_SUPPRESS, true},
+ {GetObjectSuppression.SUPPRESS, GetIntSuppression.SUPPRESS,
+ FieldSuppression.DONT_SUPPRESS, true},
+ {GetObjectSuppression.DONT_SUPPRESS, GetIntSuppression.DONT_SUPPRESS,
+ FieldSuppression.SUPPRESS, true},
+ {GetObjectSuppression.DONT_SUPPRESS, GetIntSuppression.SUPPRESS,
+ FieldSuppression.SUPPRESS, true},
+ {GetObjectSuppression.SUPPRESS, GetIntSuppression.DONT_SUPPRESS,
+ FieldSuppression.SUPPRESS, false},
+ {GetObjectSuppression.SUPPRESS, GetIntSuppression.SUPPRESS,
+ FieldSuppression.SUPPRESS, false},});
+ }
+
+ @Test
+ public void verifySuppression() throws Exception {
+ getObjectSuppression.doIt();
+ getIntSuppression.doIt();
+ fieldSuppression.doIt();
+
+ assertEquals("getObject return-value",
+ getObjectSuppression.expectedReturnValue,
+ new SuppressMethod().getObject());
+ assertEquals("getInt return-value",
+ getIntSuppression.expectedReturnValue,
+ new SuppressMethod().getInt());
+ assertThat("Value from field",
+ new SuppressField().getDomainObject(),
+ is(fieldSuppression.expectation));
+
+ if (suppressConstructor) {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+ } else {
+ expectedException.expect(RuntimeException.class);
+ }
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+ assertTrue("Or a runtime exception should have been thrown by now", suppressConstructor);
+
+ assertEquals(42, tested.getNumber());
+ assertNull(tested.getMessage());
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SystemClassUserTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SystemClassUserTest.java
new file mode 100644
index 0000000..9ec25e2
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/SystemClassUserTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.model.Statement;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import powermock.modules.test.mockito.junit4.delegate.SystemClassUserCases;
+import powermock.modules.test.mockito.junit4.delegate.SystemClassUserMethod;
+import samples.system.SystemClassUser;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+ at PrepareForTest({SystemClassUserCases.class, SystemClassUser.class})
+public class SystemClassUserTest {
+
+ final Statement test;
+
+ public SystemClassUserTest(final SystemClassUserMethod testCase) {
+ test = new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ try {
+ testCase.getMethod().invoke(new SystemClassUserCases());
+ } catch (InvocationTargetException ex) {
+ throw ex.getTargetException();
+ }
+ }
+ };
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<?> paramValues() {
+ List<Object[]> values = new ArrayList<Object[]>();
+ for (SystemClassUserMethod tstCase : SystemClassUserMethod.values()) {
+ values.add(new Object[]{tstCase});
+ }
+ return values;
+ }
+
+ @Test
+ public void __() throws Throwable {
+ test.evaluate();
+ }
+}
diff --git a/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/WhenNewTest.java b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/WhenNewTest.java
new file mode 100644
index 0000000..6ef5185
--- /dev/null
+++ b/modules/module-test/mockito/junit4-delegate/src/test/java/powermock/modules/test/mockito/junit4/delegate/parameterized/WhenNewTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package powermock.modules.test.mockito.junit4.delegate.parameterized;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import samples.expectnew.ExpectNewDemo;
+import samples.newmocking.MyClass;
+
+import java.io.DataInputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.PowerMockRunnerDelegate;
+import powermock.modules.test.mockito.junit4.delegate.WhenNewCaseMethod;
+
+ at PrepareForTest({MyClass.class, ExpectNewDemo.class, DataInputStream.class})
+ at RunWith(PowerMockRunner.class)
+ at PowerMockRunnerDelegate(Parameterized.class)
+public class WhenNewTest {
+
+ @Rule
+ public final ExpectedException ee = ExpectedException.none();
+
+ @Parameterized.Parameter(0)
+ public WhenNewCaseMethod whenNewCase;
+
+ @Test
+ public void test() throws Throwable {
+ if (whenNewCase.nullPointerIsExpected()) {
+ ee.expect(NullPointerException.class);
+ }
+ whenNewCase.runTest();
+ }
+
+ @Parameterized.Parameters(name = "{0}")
+ public static Collection<Object[]> whenNewCases() {
+ WhenNewCaseMethod[] cases = WhenNewCaseMethod.values();
+ List<Object[]> paramValues = new ArrayList<Object[]>(cases.length);
+ for (WhenNewCaseMethod each : cases) {
+ paramValues.add(new Object[]{each});
+ }
+ return paramValues;
+ }
+}
diff --git a/modules/module-test/mockito/junit4-java8-agent/pom.xml b/modules/module-test/mockito/junit4-java8-agent/pom.xml
new file mode 100644
index 0000000..8172b0d
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-agent/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-module-test-mockito-junit4-java8-agent</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with JUnit 4.x Agent. and Java8.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule-agent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-javaagent</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java b/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
new file mode 100644
index 0000000..01ef7f6
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
@@ -0,0 +1,12 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public class ClassUsesInterface {
+
+ public String saySomething(){
+ return InterfaceWithStatic.sayHello();
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java b/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
new file mode 100644
index 0000000..efb7743
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-agent/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
@@ -0,0 +1,12 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public interface InterfaceWithStatic {
+
+ static String sayHello(){
+ return "What's up?";
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8-agent/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java b/modules/module-test/mockito/junit4-java8-agent/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java
new file mode 100644
index 0000000..b17c495
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-agent/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java
@@ -0,0 +1,42 @@
+package samples.powermockito.junit4.bugs.github510;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ *
+ */
+ at PrepareForTest(InterfaceWithStatic.class)
+public class ClassUsesInterfaceTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ public ClassUsesInterface classUsesInterface;
+
+ @Before
+ public void setUp() throws Exception {
+ classUsesInterface = new ClassUsesInterface();
+
+ mockStatic(InterfaceWithStatic.class);
+ }
+
+
+
+ @Test
+ public void testSaySomething() throws Exception {
+ final String value = "Hi Man";
+ when(InterfaceWithStatic.sayHello()).thenReturn(value);
+
+ assertThat(classUsesInterface.saySomething()).isEqualTo(value);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8-rule-xstream/pom.xml b/modules/module-test/mockito/junit4-java8-rule-xstream/pom.xml
new file mode 100644
index 0000000..de7dd9a
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-rule-xstream/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-module-test-mockito-junit4-java8-rule-xstream</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with JUnit 4.x, Java8 and rules-xstream.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java b/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
new file mode 100644
index 0000000..01ef7f6
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
@@ -0,0 +1,12 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public class ClassUsesInterface {
+
+ public String saySomething(){
+ return InterfaceWithStatic.sayHello();
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java b/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
new file mode 100644
index 0000000..efb7743
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-rule-xstream/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
@@ -0,0 +1,12 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public interface InterfaceWithStatic {
+
+ static String sayHello(){
+ return "What's up?";
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8-rule-xstream/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java b/modules/module-test/mockito/junit4-java8-rule-xstream/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java
new file mode 100644
index 0000000..b17c495
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8-rule-xstream/src/test/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterfaceTest.java
@@ -0,0 +1,42 @@
+package samples.powermockito.junit4.bugs.github510;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ *
+ */
+ at PrepareForTest(InterfaceWithStatic.class)
+public class ClassUsesInterfaceTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ public ClassUsesInterface classUsesInterface;
+
+ @Before
+ public void setUp() throws Exception {
+ classUsesInterface = new ClassUsesInterface();
+
+ mockStatic(InterfaceWithStatic.class);
+ }
+
+
+
+ @Test
+ public void testSaySomething() throws Exception {
+ final String value = "Hi Man";
+ when(InterfaceWithStatic.sayHello()).thenReturn(value);
+
+ assertThat(classUsesInterface.saySomething()).isEqualTo(value);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8/pom.xml b/modules/module-test/mockito/junit4-java8/pom.xml
new file mode 100644
index 0000000..4509c56
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-module-test-mockito-junit4-java8</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with JUnit 4.x. and Java8.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
new file mode 100644
index 0000000..c4a0718
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ClassUsesInterface.java
@@ -0,0 +1,16 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public class ClassUsesInterface {
+
+ public String saySomething(){
+ return InterfaceWithStatic.sayHello();
+ }
+
+ public String createAndSay(){
+ return InterfaceWithStatic.createAndSay();
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ConstructorObject.java b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ConstructorObject.java
new file mode 100644
index 0000000..0e21f09
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/ConstructorObject.java
@@ -0,0 +1,10 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public class ConstructorObject {
+ public String sayHello() {
+ return null;
+ }
+}
diff --git a/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
new file mode 100644
index 0000000..99089da
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/bugs/github510/InterfaceWithStatic.java
@@ -0,0 +1,16 @@
+package samples.powermockito.junit4.bugs.github510;
+
+/**
+ *
+ */
+public interface InterfaceWithStatic {
+
+ static String sayHello(){
+ return "What's up?";
+ }
+
+ static String createAndSay(){
+ return new ConstructorObject().sayHello();
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/largemethod/InterfaceMethodExceedingJvmLimit.java b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/largemethod/InterfaceMethodExceedingJvmLimit.java
new file mode 100644
index 0000000..e57d00a
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/main/java/samples/powermockito/junit4/largemethod/InterfaceMethodExceedingJvmLimit.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.powermockito.junit4.largemethod;
+
+/**
+ * Example of class with method which after instrumentation is larger than JVM limit.
+ */
+public interface InterfaceMethodExceedingJvmLimit {
+
+ /**
+ * Method size after instrumentation is equal to 91265.
+ */
+ static String init() {
+ String a = "A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ return a;
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8/src/test/java/org/powermock/modules/junit4/largemethod/LargeMethodInInterfaceTest.java b/modules/module-test/mockito/junit4-java8/src/test/java/org/powermock/modules/junit4/largemethod/LargeMethodInInterfaceTest.java
new file mode 100644
index 0000000..425b03e
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/test/java/org/powermock/modules/junit4/largemethod/LargeMethodInInterfaceTest.java
@@ -0,0 +1,56 @@
+package org.powermock.modules.junit4.largemethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.powermockito.junit4.largemethod.InterfaceMethodExceedingJvmLimit;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(InterfaceMethodExceedingJvmLimit.class)
+public class LargeMethodInInterfaceTest {
+
+ @Test
+ public void largeMethodShouldBeOverridden() {
+ try {
+ InterfaceMethodExceedingJvmLimit.init();
+ fail("Method should be overridden and exception should be thrown");
+ } catch (Exception e) {
+ assertSame(IllegalAccessException.class, e.getClass());
+ assertTrue(e.getMessage().contains("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeSuppressed() {
+ suppress(PowerMockito.method(InterfaceMethodExceedingJvmLimit.class, "init"));
+ assertNull("Suppressed method should return: null", InterfaceMethodExceedingJvmLimit.init());
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeMocked() {
+ mockStatic(InterfaceMethodExceedingJvmLimit.class);
+ when(InterfaceMethodExceedingJvmLimit.init()).thenReturn("ok");
+ assertEquals("Mocked method should return: ok", "ok", InterfaceMethodExceedingJvmLimit.init());
+ verifyStatic();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void largeMethodShouldBeAbleToBeMockedAndThrowException() {
+ mockStatic(InterfaceMethodExceedingJvmLimit.class);
+ when(InterfaceMethodExceedingJvmLimit.init()).thenThrow(new IllegalStateException());
+ InterfaceMethodExceedingJvmLimit.init();
+ verifyStatic();
+ }
+}
diff --git a/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/Github510Test.java b/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/Github510Test.java
new file mode 100644
index 0000000..26239ea
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/Github510Test.java
@@ -0,0 +1,51 @@
+package samples.powermockito.junit4.bugs.github510;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({InterfaceWithStatic.class, ConstructorObject.class})
+public class Github510Test {
+
+ public ClassUsesInterface classUsesInterface;
+
+ @Before
+ public void setUp() throws Exception {
+ classUsesInterface = new ClassUsesInterface();
+ }
+
+ @Test
+ public void testSaySomething() throws Exception {
+ final String value = "Hi Man";
+
+ mockStatic(InterfaceWithStatic.class);
+ when(InterfaceWithStatic.sayHello()).thenReturn(value);
+
+ assertThat(classUsesInterface.saySomething()).isEqualTo(value);
+ }
+
+ @Test
+ public void testInterfaceStaticCallsConstructor() throws Exception {
+ final String value = "Hi Man";
+
+ ConstructorObject constructorObject = mock(ConstructorObject.class);
+ when(constructorObject.sayHello()).thenReturn(value);
+
+
+ whenNew(ConstructorObject.class).withNoArguments().thenReturn(constructorObject);
+
+ assertThat(classUsesInterface.createAndSay()).isEqualTo(value);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java b/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java
new file mode 100644
index 0000000..d52f8e0
--- /dev/null
+++ b/modules/module-test/mockito/junit4-java8/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/510
+ */
+package samples.powermockito.junit4.bugs.github510;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/pom.xml b/modules/module-test/mockito/junit4-rule-objenesis/pom.xml
new file mode 100644
index 0000000..175cc89
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-junit4-rule-objenesis-test</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for PowerMock Rule using Objenesis Deepcloning
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-objenesis</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/FinalDemoTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/FinalDemoTest.java
new file mode 100644
index 0000000..ab9dfc0
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/FinalDemoTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito.
+ */
+ at PrepareForTest( { FinalDemo.class, PrivateFinal.class })
+public class FinalDemoTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertMockFinalWithNoExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ assertNull(tested.say(argument));
+
+ verify(tested).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+ final String expected = "Hello altered World";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.say(argument)).thenReturn(expected);
+
+ final String actual = tested.say(argument);
+
+ verify(tested).say(argument);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertFinalNativeWithExpectationsWorks() throws Exception {
+ final String expected = "Hello altered World";
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.sayFinalNative(argument)).thenReturn("Hello altered World");
+
+ String actual = tested.sayFinalNative(argument);
+
+ verify(tested).sayFinalNative(argument);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertSpyingOnFinalInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ final String argument = "PowerMock";
+ final String expected = "something";
+
+ assertEquals("Hello " + argument, spy.say(argument));
+ when(spy.say(argument)).thenReturn(expected);
+ assertEquals(expected, spy.say(argument));
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void assertSpyingOnFinalVoidInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ doThrow(new ArrayStoreException()).when(spy).finalVoidCallee();
+
+ spy.finalVoidCaller();
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorks() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ when(spy, "sayIt", isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke("sayIt", expected);
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorksWhenUsingJavaLangReflectMethod() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ final Method methodToExpect = method(PrivateFinal.class, "sayIt");
+ when(spy, methodToExpect).withArguments(isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke(methodToExpect).withArguments(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/Foo.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/Foo.java
new file mode 100644
index 0000000..0e6f803
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/Foo.java
@@ -0,0 +1,23 @@
+package samples.powermockito.junit4.rule.objenesis;
+
+public class Foo {
+
+ public Bar m() {
+ return new Bar(1);
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ public static class Bar {
+
+ private final int i;
+
+ Bar(final int i) {
+ this.i = i;
+ }
+
+ public int getI() {
+ return i;
+ }
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/MockStaticTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/MockStaticTest.java
new file mode 100644
index 0000000..b978312
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/MockStaticTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+
+/**
+ * Test class to demonstrate static mocking with PowerMockito.
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void testMockStaticNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticWithExpectations() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say(argument);
+ }
+
+ @Test
+ public void errorousVerificationOfStaticMethodsGivesANonMockitoStandardMessage() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ try {
+ StaticService.say(argument);
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.singleton.StaticService.say(\"hello\");\nWanted 2 times but was 1 time.", e.getMessage());
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testMockStaticThatThrowsException() throws Exception {
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenThrow(new IllegalStateException());
+
+ StaticService.say(argument);
+ }
+
+ @Test(expected = ArgumentsAreDifferent.class)
+ public void testMockStaticVerificationFails() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("Hello");
+ }
+
+ @Test
+ public void testMockStaticAtLeastOnce() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(atLeastOnce());
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticCorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ StaticService.say("hello");
+ }
+
+ @Test(expected = TooLittleActualInvocations.class)
+ public void testMockStaticIncorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(3));
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticVoidWithNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+
+ StaticService.sayHello();
+
+ verifyStatic();
+ StaticService.sayHello();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void testMockStaticVoidWhenThrowingException() throws Exception {
+ mockStatic(StaticService.class);
+
+ // Expectations
+ doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
+ StaticService.sayHello();
+
+ // Test
+ StaticService.sayHello();
+ }
+
+ @Test
+ public void testSpyOnStaticMethods() throws Exception {
+ spy(StaticService.class);
+
+ String expectedMockValue = "expected";
+ when(StaticService.say("world")).thenReturn(expectedMockValue);
+
+ assertEquals(expectedMockValue, StaticService.say("world"));
+ assertEquals("Hello world2", StaticService.say("world2"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PowerMockRuleTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PowerMockRuleTest.java
new file mode 100644
index 0000000..fe8a21a
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PowerMockRuleTest.java
@@ -0,0 +1,52 @@
+package samples.powermockito.junit4.rule.objenesis;
+
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import samples.powermockito.junit4.rule.objenesis.Foo.Bar;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+ at PowerMockIgnore({"org.mockito.*","org.powermock.api.mockito.repackaged.*"})
+ at PrepareForTest(Foo.class)
+ at MockPolicy(PowerMockRuleTest.CustomPolicy.class)
+public class PowerMockRuleTest {
+
+ @Rule
+ public final PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void test1() {
+ assertEquals(999, new Foo().m().getI());
+ }
+
+ @Test
+ public void test2() {
+ assertEquals(999, new Foo().m().getI());
+ }
+
+ public static class CustomPolicy implements PowerMockPolicy {
+
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ final Bar barMock = mock(Bar.class);
+ when(barMock.getI()).thenReturn(999);
+ settings.stubMethod(Whitebox.getMethod(Foo.class, "m"), barMock);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PrivateInstanceMockingTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PrivateInstanceMockingTest.java
new file mode 100644
index 0000000..9449db9
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/PrivateInstanceMockingTest.java
@@ -0,0 +1,117 @@
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.privateandfinal.PrivateFinal;
+import samples.privatemocking.PrivateMethodDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.never;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at PrepareForTest( { PrivateMethodDemo.class })
+public class PrivateInstanceMockingTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", 12, "test").thenReturn("another");
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ }
+
+ @Test
+ public void expectationsWorkWithArgumentMatchersWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ verifyPrivate(tested).invoke("doSayYear", 50, "Temp");
+ }
+
+ @Test
+ public void errorousVerificationOnPrivateMethodGivesFilteredErrorMessage() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ try {
+ verifyPrivate(tested, never()).invoke("doSayYear", 50, "Temp");
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.privatemocking.PrivateMethodDemo.doSayYear(\n 50,\n \"Temp\"\n);\nNever wanted but invoked .", e
+ .getMessage());
+ }
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectationsWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(Object.class)).thenThrow(new ArrayStoreException());
+
+ tested.doObjectStuff(new Object());
+ }
+
+ @Test
+ public void answersWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(String.class)).thenAnswer(new Answer<Void>() {
+ private static final long serialVersionUID = 20645008237481667L;
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Testing", invocation.getArguments()[0]);
+ return null;
+ }
+ });
+ tested.doObjectStuff(new Object());
+ tested.doObjectStuff("Testing");
+ }
+
+ @Test
+ public void spyingOnPrivateFinalMethodsWorksWhenClassIsNotFinal() throws Exception {
+ PrivateFinal tested = spy(new PrivateFinal());
+
+ final String name = "test";
+ tested.say(name);
+ assertEquals("Hello " + name, tested.say(name));
+
+ when(tested, "sayIt", name).thenReturn("First", "Second");
+
+ assertEquals("First", tested.say(name));
+ assertEquals("Second", tested.say(name));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/StaticInitializerExampleTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/StaticInitializerExampleTest.java
new file mode 100644
index 0000000..1412913
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/StaticInitializerExampleTest.java
@@ -0,0 +1,28 @@
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import samples.staticinitializer.StaticInitializerExample;
+
+import java.util.HashSet;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+ at SuppressStaticInitializationFor("samples.staticinitializer.StaticInitializerExample")
+public class StaticInitializerExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void testSupressStaticInitializerAndSetFinalField() throws Exception {
+ assertNull("Should be null because the static initializer should be suppressed", StaticInitializerExample.getMySet());
+ final HashSet<String> hashSet = new HashSet<String>();
+ Whitebox.setInternalState(StaticInitializerExample.class, "mySet", hashSet);
+ assertSame(hashSet, Whitebox.getInternalState(StaticInitializerExample.class, "mySet"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/SystemClassUserTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/SystemClassUserTest.java
new file mode 100644
index 0000000..1fa7e9b
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/SystemClassUserTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.system.SystemClassUser;
+
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at PrepareForTest( { SystemClassUser.class })
+ at Ignore
+public class SystemClassUserTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ when(URLEncoder.encode("string", "enc")).thenReturn("something");
+
+ assertEquals("something", new SystemClassUser().performEncode());
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = mock(Runtime.class);
+ Process processMock = mock(Process.class);
+
+ when(Runtime.getRuntime()).thenReturn(runtimeMock);
+ when(runtimeMock.exec("command")).thenReturn(processMock);
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ spy(System.class);
+
+ when(System.nanoTime()).thenReturn(2L);
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyStatic(times(2));
+ Collections.shuffle(list);
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ spy(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ when(String.format(string, args)).thenReturn(returnValue);
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/WhenNewTest.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/WhenNewTest.java
new file mode 100644
index 0000000..4286db1
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/WhenNewTest.java
@@ -0,0 +1,602 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.objenesis;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate new instance mocking using whenConstructionOf(..).
+ *
+ */
+ at SuppressWarnings("PrimitiveArrayArgumentToVariableArgMethod")
+ at Ignore("Since upgrading to JVM 1.6.0_24 lots of tests started to fail")
+ at PrepareForTest({ MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class WhenNewTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new IOException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage()).thenReturn("Hello altered World");
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock).getMessage();
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage("test")).thenReturn("Hello altered World");
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock).getMessage("test");
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ doNothing().when(myClassMock).voidMethod();
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock).voidMethod();
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new RuntimeException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+ try {
+ verifyNew(MyClass.class, times(1)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 1 time but was 3 times.", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ try {
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 2 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ //
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ whenNew(DataInputStream.class).withArguments(null).thenThrow(new RuntimeException("error"));
+
+ InputStream stream = tested.alternativePath();
+
+ verifyNew(DataInputStream.class).withArguments(null);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.",
+ stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withParameterTypes(Service.class, int.class)
+ .withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithConstructorUsingParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class, Service.class, int.class)).withArguments(serviceMock,
+ numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewUsingConstructorWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class)).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllMessages()).thenReturn(new String[] { firstString, secondString });
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ whenNew(VarArgsConstructorDemo.class).withArguments(object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName()
+ + "' with parameter types: [ " + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = mock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllServices()).thenReturn(new Service[] { serviceMock });
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull()
+ throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ /*
+ * Should throw NPE because the default behavior of Mockito when a
+ * something isn't expected is to return a default value. In this case
+ * whenConstructionOf
+ * (ExpectNewServiceUser.class).withArguments(serviceMock,
+ * numberOfTimes) is the wrong expectation and thus null is returned
+ * from the substitute mock which is the correct behavior.
+ */
+ fail("Should throw NPE!");
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.makeDate();
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "Wanted but not invoked samples.newmocking.MyClass();\nActually, there were zero interactions with this mock.",
+ e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/Github512Test.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/Github512Test.java
new file mode 100644
index 0000000..4e61f4c
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/Github512Test.java
@@ -0,0 +1,24 @@
+package samples.powermockito.junit4.rule.objenesis.bugs.github512;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.method;
+import static org.powermock.api.mockito.PowerMockito.suppress;
+
+public class Github512Test {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ @PrepareForTest(StaticService.class)
+ public void shouldSuppressMethodWithPrepareForTestOnMethod() {
+ suppress(method(StaticService.class, "calculate"));
+ assertThat(StaticService.calculate(1, 5)).isEqualTo(0);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/package-info.java b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/package-info.java
new file mode 100644
index 0000000..d85f980
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-objenesis/src/test/java/samples/powermockito/junit4/rule/objenesis/bugs/github512/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/512
+ */
+package samples.powermockito.junit4.rule.objenesis.bugs.github512;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-xstream/pom.xml b/modules/module-test/mockito/junit4-rule-xstream/pom.xml
new file mode 100644
index 0000000..dd051ed
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-junit4-rule-xstream-test</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for PowerMock Rule using XStream Deepcloning
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-rule</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-xstream</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/AssertPowerMockRuleDelagatesToOtherRulesTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/AssertPowerMockRuleDelagatesToOtherRulesTest.java
new file mode 100644
index 0000000..b538e38
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/AssertPowerMockRuleDelagatesToOtherRulesTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.core.classloader.MockClassLoader;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static junit.framework.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * This test demonstrates that the PowerMockRule delegates to other rules.
+ */
+public class AssertPowerMockRuleDelagatesToOtherRulesTest {
+ private static final MyObject BEFORE = new MyObject();
+
+ private final List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertPowerMockRuleDelegatesToOtherRules() throws Exception {
+ assertTrue(this.getClass().getClassLoader().getClass().getName().contains(MockClassLoader.class.getName()));
+ assertEquals(1, objects.size());
+ // Not same using X-Stream
+ assertEquals(BEFORE, objects.get(0));
+ assertEquals("assertPowerMockRuleDelegatesToOtherRules", testName.getMethodName());
+ }
+
+ private class MyRule implements MethodRule {
+ public Statement apply(final Statement base, FrameworkMethod method, Object target) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ base.evaluate();
+ }
+ };
+ }
+ }
+
+ private static class MyObject {
+ private final String state = "state";
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ MyObject myObject = (MyObject) o;
+
+ return state != null ? state.equals(myObject.state) : myObject.state == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return state.hashCode();
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/FinalDemoTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/FinalDemoTest.java
new file mode 100644
index 0000000..2bc2843
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/FinalDemoTest.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito.
+ */
+ at PrepareForTest( { FinalDemo.class, PrivateFinal.class })
+public class FinalDemoTest {
+
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertMockFinalWithNoExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ assertNull(tested.say(argument));
+
+ verify(tested).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+ final String expected = "Hello altered World";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.say(argument)).thenReturn(expected);
+
+ final String actual = tested.say(argument);
+
+ verify(tested).say(argument);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertFinalNativeWithExpectationsWorks() throws Exception {
+ final String expected = "Hello altered World";
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.sayFinalNative(argument)).thenReturn("Hello altered World");
+
+ String actual = tested.sayFinalNative(argument);
+
+ verify(tested).sayFinalNative(argument);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertSpyingOnFinalInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ final String argument = "PowerMock";
+ final String expected = "something";
+
+ assertEquals("Hello " + argument, spy.say(argument));
+ when(spy.say(argument)).thenReturn(expected);
+ assertEquals(expected, spy.say(argument));
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void assertSpyingOnFinalVoidInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ doThrow(new ArrayStoreException()).when(spy).finalVoidCallee();
+
+ spy.finalVoidCaller();
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorks() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ when(spy, "sayIt", isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke("sayIt", expected);
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorksWhenUsingJavaLangReflectMethod() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ final Method methodToExpect = method(PrivateFinal.class, "sayIt");
+ when(spy, methodToExpect).withArguments(isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke(methodToExpect).withArguments(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/Foo.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/Foo.java
new file mode 100644
index 0000000..b590f79
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/Foo.java
@@ -0,0 +1,23 @@
+package samples.powermockito.junit4.rule.xstream;
+
+public class Foo {
+
+ public Bar m() {
+ return new Bar(1);
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ public static class Bar {
+
+ private final int i;
+
+ Bar(final int i) {
+ this.i = i;
+ }
+
+ public int getI() {
+ return i;
+ }
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/MockStaticTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/MockStaticTest.java
new file mode 100644
index 0000000..6c168bf
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/MockStaticTest.java
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+
+/**
+ * Test class to demonstrate static mocking with PowerMockito.
+ */
+ at PrepareForTest( { StaticService.class, StaticHelper.class })
+public class MockStaticTest {
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void testMockStaticNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticWithExpectations() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say(argument);
+ }
+
+ @Test
+ public void errorousVerificationOfStaticMethodsGivesANonMockitoStandardMessage() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ try {
+ StaticService.say(argument);
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.singleton.StaticService.say(\"hello\");\nWanted 2 times but was 1 time.", e.getMessage());
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testMockStaticThatThrowsException() throws Exception {
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenThrow(new IllegalStateException());
+
+ StaticService.say(argument);
+ }
+
+ @Test(expected = ArgumentsAreDifferent.class)
+ public void testMockStaticVerificationFails() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("Hello");
+ }
+
+ @Test
+ public void testMockStaticAtLeastOnce() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(atLeastOnce());
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticCorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ StaticService.say("hello");
+ }
+
+ @Test(expected = TooLittleActualInvocations.class)
+ public void testMockStaticIncorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(3));
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticVoidWithNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+
+ StaticService.sayHello();
+
+ verifyStatic();
+ StaticService.sayHello();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void testMockStaticVoidWhenThrowingException() throws Exception {
+ mockStatic(StaticService.class);
+
+ // Expectations
+ doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
+ StaticService.sayHello();
+
+ // Test
+ StaticService.sayHello();
+ }
+
+ @Test
+ public void testSpyOnStaticMethods() throws Exception {
+ spy(StaticService.class);
+
+ String expectedMockValue = "expected";
+ when(StaticService.say("world")).thenReturn(expectedMockValue);
+
+ assertEquals(expectedMockValue, StaticService.say("world"));
+ assertEquals("Hello world2", StaticService.say("world2"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PowerMockRuleTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PowerMockRuleTest.java
new file mode 100644
index 0000000..d927279
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PowerMockRuleTest.java
@@ -0,0 +1,52 @@
+package samples.powermockito.junit4.rule.xstream;
+
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.MockPolicy;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.spi.PowerMockPolicy;
+import org.powermock.mockpolicies.MockPolicyClassLoadingSettings;
+import org.powermock.mockpolicies.MockPolicyInterceptionSettings;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import samples.powermockito.junit4.rule.xstream.Foo.Bar;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+ at PowerMockIgnore({"org.mockito.*","org.powermock.api.mockito.repackaged.*"})
+ at PrepareForTest(Foo.class)
+ at MockPolicy(PowerMockRuleTest.CustomPolicy.class)
+public class PowerMockRuleTest {
+
+ @Rule
+ public final PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void test1() {
+ assertEquals(999, new Foo().m().getI());
+ }
+
+ @Test
+ public void test2() {
+ assertEquals(999, new Foo().m().getI());
+ }
+
+ public static class CustomPolicy implements PowerMockPolicy {
+
+ @Override
+ public void applyClassLoadingPolicy(MockPolicyClassLoadingSettings settings) {
+ }
+
+ @Override
+ public void applyInterceptionPolicy(MockPolicyInterceptionSettings settings) {
+ final Bar barMock = mock(Bar.class);
+ when(barMock.getI()).thenReturn(999);
+ settings.stubMethod(Whitebox.getMethod(Foo.class, "m"), barMock);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PrivateInstanceMockingTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PrivateInstanceMockingTest.java
new file mode 100644
index 0000000..76ca693
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/PrivateInstanceMockingTest.java
@@ -0,0 +1,116 @@
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.privateandfinal.PrivateFinal;
+import samples.privatemocking.PrivateMethodDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.never;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at PrepareForTest( { PrivateMethodDemo.class })
+public class PrivateInstanceMockingTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", 12, "test").thenReturn("another");
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ }
+
+ @Test
+ public void expectationsWorkWithArgumentMatchersWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ verifyPrivate(tested).invoke("doSayYear", 50, "Temp");
+ }
+
+ @Test
+ public void errorousVerificationOnPrivateMethodGivesFilteredErrorMessage() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ try {
+ verifyPrivate(tested, never()).invoke("doSayYear", 50, "Temp");
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.privatemocking.PrivateMethodDemo.doSayYear(\n 50,\n \"Temp\"\n);\nNever wanted but invoked .", e
+ .getMessage());
+ }
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectationsWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(Object.class)).thenThrow(new ArrayStoreException());
+
+ tested.doObjectStuff(new Object());
+ }
+
+ @Test
+ public void answersWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(String.class)).thenAnswer(new Answer<Void>() {
+ private static final long serialVersionUID = 20645008237481667L;
+
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Testing", invocation.getArguments()[0]);
+ return null;
+ }
+ });
+ tested.doObjectStuff(new Object());
+ tested.doObjectStuff("Testing");
+ }
+
+ @Test
+ public void spyingOnPrivateFinalMethodsWorksWhenClassIsNotFinal() throws Exception {
+ PrivateFinal tested = spy(new PrivateFinal());
+
+ final String name = "test";
+ tested.say(name);
+ assertEquals("Hello " + name, tested.say(name));
+
+ when(tested, "sayIt", name).thenReturn("First", "Second");
+
+ assertEquals("First", tested.say(name));
+ assertEquals("Second", tested.say(name));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/StaticInitializerExampleTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/StaticInitializerExampleTest.java
new file mode 100644
index 0000000..979e7a5
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/StaticInitializerExampleTest.java
@@ -0,0 +1,28 @@
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import samples.staticinitializer.StaticInitializerExample;
+
+import java.util.HashSet;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+
+ at SuppressStaticInitializationFor("samples.staticinitializer.StaticInitializerExample")
+public class StaticInitializerExampleTest {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ public void testSupressStaticInitializerAndSetFinalField() throws Exception {
+ assertNull("Should be null because the static initializer should be suppressed", StaticInitializerExample.getMySet());
+ final HashSet<String> hashSet = new HashSet<String>();
+ Whitebox.setInternalState(StaticInitializerExample.class, "mySet", hashSet);
+ assertSame(hashSet, Whitebox.getInternalState(StaticInitializerExample.class, "mySet"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/SystemClassUserTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/SystemClassUserTest.java
new file mode 100644
index 0000000..da00aa9
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/SystemClassUserTest.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.system.SystemClassUser;
+
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at PrepareForTest( { SystemClassUser.class })
+ at Ignore
+public class SystemClassUserTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ when(URLEncoder.encode("string", "enc")).thenReturn("something");
+
+ assertEquals("something", new SystemClassUser().performEncode());
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = mock(Runtime.class);
+ Process processMock = mock(Process.class);
+
+ when(Runtime.getRuntime()).thenReturn(runtimeMock);
+ when(runtimeMock.exec("command")).thenReturn(processMock);
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ spy(System.class);
+
+ when(System.nanoTime()).thenReturn(2L);
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyStatic(times(2));
+ Collections.shuffle(list);
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ spy(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ when(String.format(string, args)).thenReturn(returnValue);
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/WhenNewTest.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/WhenNewTest.java
new file mode 100644
index 0000000..72970cf
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/WhenNewTest.java
@@ -0,0 +1,601 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rule.xstream;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate new instance mocking using whenConstructionOf(..).
+ *
+ */
+ at SuppressWarnings("PrimitiveArrayArgumentToVariableArgMethod")
+ at PrepareForTest({ MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class WhenNewTest {
+ @Rule
+ public PowerMockRule powerMockRule = new PowerMockRule();
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new IOException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage()).thenReturn("Hello altered World");
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock).getMessage();
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage("test")).thenReturn("Hello altered World");
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock).getMessage("test");
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ doNothing().when(myClassMock).voidMethod();
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock).voidMethod();
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new RuntimeException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+ try {
+ verifyNew(MyClass.class, times(1)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 1 time but was 3 times.", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ try {
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 2 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ //
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ whenNew(DataInputStream.class).withArguments(null).thenThrow(new RuntimeException("error"));
+
+ InputStream stream = tested.alternativePath();
+
+ verifyNew(DataInputStream.class).withArguments(null);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.",
+ stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withParameterTypes(Service.class, int.class)
+ .withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithConstructorUsingParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class, Service.class, int.class)).withArguments(serviceMock,
+ numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewUsingConstructorWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class)).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllMessages()).thenReturn(new String[] { firstString, secondString });
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ whenNew(VarArgsConstructorDemo.class).withArguments(object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName()
+ + "' with parameter types: [ " + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = mock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ @Override
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllServices()).thenReturn(new Service[] { serviceMock });
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull()
+ throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(
+ varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ /*
+ * Should throw NPE because the default behavior of Mockito when a
+ * something isn't expected is to return a default value. In this case
+ * whenConstructionOf
+ * (ExpectNewServiceUser.class).withArguments(serviceMock,
+ * numberOfTimes) is the wrong expectation and thus null is returned
+ * from the substitute mock which is the correct behavior.
+ */
+ fail("Should throw NPE!");
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.makeDate();
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals(
+ "Wanted but not invoked samples.newmocking.MyClass();\nActually, there were zero interactions with this mock.",
+ e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/Github512Test.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/Github512Test.java
new file mode 100644
index 0000000..94de30a
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/Github512Test.java
@@ -0,0 +1,24 @@
+package samples.powermockito.junit4.rule.xstream.github512;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.rule.PowerMockRule;
+import samples.singleton.StaticService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.powermock.api.mockito.PowerMockito.method;
+import static org.powermock.api.mockito.PowerMockito.suppress;
+
+public class Github512Test {
+
+ @Rule
+ public PowerMockRule rule = new PowerMockRule();
+
+ @Test
+ @PrepareForTest(StaticService.class)
+ public void shouldSuppressMethodWithPrepareForTestOnMethod() {
+ suppress(method(StaticService.class, "calculate"));
+ assertThat(StaticService.calculate(1, 5)).isEqualTo(0);
+ }
+}
diff --git a/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/package-info.java b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/package-info.java
new file mode 100644
index 0000000..fb4ddf2
--- /dev/null
+++ b/modules/module-test/mockito/junit4-rule-xstream/src/test/java/samples/powermockito/junit4/rule/xstream/github512/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/512
+ */
+package samples.powermockito.junit4.rule.xstream.github512;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/pom.xml b/modules/module-test/mockito/junit4/pom.xml
new file mode 100644
index 0000000..394cab8
--- /dev/null
+++ b/modules/module-test/mockito/junit4/pom.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-mockito-junit4</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with JUnit 4.x.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/ClassLoaderBugTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/ClassLoaderBugTest.java
new file mode 100644
index 0000000..a1527f4
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/ClassLoaderBugTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import static org.junit.Assert.assertEquals;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(TestClass.class)
+public class ClassLoaderBugTest {
+
+ /**
+ * See issue <a href="https://code.google.com/p/powermock/issues/detail?id=426">426</a> for more details.
+ */
+ @Test(timeout = 2000)
+ public void resourcesAreNotLoadedTwice() throws IOException {
+ String resourceName = getClass().getCanonicalName().replace(".", "/") + ".class";
+ Enumeration<URL> enumeration = getClass().getClassLoader().getResources(resourceName);
+
+ int count = 0;
+ while (enumeration.hasMoreElements()) {
+ System.out.println(enumeration.nextElement().toString());
+ count++;
+ }
+
+ assertEquals(1, count);
+ }
+
+}
+
+class TestClass {
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClass.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClass.java
new file mode 100644
index 0000000..d880ef5
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClass.java
@@ -0,0 +1,33 @@
+package samples.powermockito.junit4;
+
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Just a testclass with a final-equals method.
+ */
+public class FinalEqualsClass {
+
+ @Override
+ public final boolean equals(Object obj) {
+ return super.equals(obj);
+ }
+
+ public final String foo() {
+ return "foo";
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClassTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClassTest.java
new file mode 100644
index 0000000..47b8df9
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/FinalEqualsClassTest.java
@@ -0,0 +1,50 @@
+package samples.powermockito.junit4;
+
+
+import static org.junit.Assert.*;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ at RunWith(value = PowerMockRunner.class)
+ at PrepareForTest({FinalEqualsClass.class})
+ at SuppressStaticInitializationFor({"samples.powermockito.junit4.FinalClass"})
+public class FinalEqualsClassTest {
+
+ @Test
+ public void callingEqualsDoesntCauseStackOverflow() throws Exception {
+ FinalEqualsClass fc = new FinalEqualsClass();
+ fc.foo();
+
+ FinalEqualsClass mock = PowerMockito.mock(FinalEqualsClass.class);
+ FinalEqualsClass mock2 = PowerMockito.mock(FinalEqualsClass.class);
+ PowerMockito.when(mock.foo()).thenReturn("bar");
+ fc = PowerMockito.spy(fc);
+ PowerMockito.when(fc.foo()).thenReturn("bar");
+ fc.equals(mock);
+ assertEquals("bar", mock.foo());
+ assertEquals("bar", fc.foo());
+
+ assertEquals(mock, mock);
+ assertFalse(mock.equals(mock2));
+
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/abstractmocking/AbstractMethodMockingTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/abstractmocking/AbstractMethodMockingTest.java
new file mode 100644
index 0000000..a38c116
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/abstractmocking/AbstractMethodMockingTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.abstractmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.abstractmocking.AbstractMethodMocking;
+
+import static org.junit.Assert.*;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { AbstractMethodMocking.class })
+public class AbstractMethodMockingTest {
+
+ @Test
+ public void mocksAbstractClasses() throws Exception {
+ assertNotNull(mock(AbstractMethodMocking.class));
+ }
+
+ @Test
+ public void canSpyOnAnonymousClasses() throws Exception {
+ AbstractMethodMocking tested = new AbstractMethodMocking() {
+ @Override
+ protected String getIt() {
+ return null;
+ }
+ };
+
+ assertNull(tested.getValue());
+ AbstractMethodMocking spy = spy(tested);
+ when(spy.getValue()).thenReturn("something");
+
+ assertEquals("something", spy.getValue());
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/CaptorAnnotationTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/CaptorAnnotationTest.java
new file mode 100644
index 0000000..2868867
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/CaptorAnnotationTest.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+import samples.privateandfinal.PrivateFinalOverload;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * Asserts that {@link Captor} with PowerMock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({FinalDemo.class, PrivateFinal.class, PrivateFinalOverload.class})
+public class CaptorAnnotationTest {
+
+ @Captor
+ private ArgumentCaptor<String> captor;
+
+ @Test
+ public void captorAnnotationWorks() throws Exception {
+ final String expected = "testing";
+ FinalDemo demo = mock(FinalDemo.class);
+ demo.say(expected);
+
+ verify(demo).say(captor.capture());
+ assertEquals(expected, captor.getValue());
+ }
+
+ @Test
+ public void captorAnnotationWorksOnPrivateMethods() throws Exception {
+ final String expected = "testing";
+ PrivateFinal demo = spy(new PrivateFinal());
+ demo.say(expected);
+
+ verifyPrivate(demo).invoke("sayIt", captor.capture());
+ assertEquals(expected, captor.getValue());
+ }
+
+ @Test
+ public void captorAnnotationWorksOnPrivateOverriddenMethods() throws Exception {
+ final String expected = "testing";
+ PrivateFinalOverload demo = spy(new PrivateFinalOverload());
+ demo.say(expected);
+
+ verifyPrivate(demo).invoke(method(PrivateFinalOverload.class, "say", String.class, String.class)).withArguments(anyString(), captor.capture());
+ assertEquals(expected, captor.getValue());
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/ChunkingAndStaticInitializerRemovalTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/ChunkingAndStaticInitializerRemovalTest.java
new file mode 100644
index 0000000..16cca58
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/ChunkingAndStaticInitializerRemovalTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.staticinitializer.SimpleStaticInitializerExample;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito and PowerMock
+ * annotations.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SimpleStaticInitializerExample.class)
+public class ChunkingAndStaticInitializerRemovalTest {
+
+ @Mock
+ private SimpleStaticInitializerExample tested;
+
+ @Test
+ public void testMockingWithNoChunking() throws Exception {
+ final String argument = "hello";
+ final String string = tested.getString();
+ assertEquals(Whitebox.getInternalState(SimpleStaticInitializerExample.class, String.class), string);
+ assertNull(tested.getConcatenatedString(argument));
+
+ verify(tested).getConcatenatedString(argument);
+ }
+
+ @SuppressStaticInitializationFor("samples.staticinitializer.SimpleStaticInitializerExample")
+ @Test
+ public void testMockingWithChunking() throws Exception {
+ final String argument = "hello";
+ assertNull(tested.getString());
+ assertNull(tested.getConcatenatedString(argument));
+
+ verify(tested).getConcatenatedString(argument);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/InjectMocksAnnotationTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/InjectMocksAnnotationTest.java
new file mode 100644
index 0000000..77ff895
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/InjectMocksAnnotationTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+import samples.injectmocks.DependencyHolder;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+/**
+ * Asserts that {@link @InjectMocks} with PowerMock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class InjectMocksAnnotationTest {
+
+ @SuppressWarnings("unused")
+ @Mock
+ private FinalDemo finalDemo;
+
+ @InjectMocks
+ private DependencyHolder dependencyHolder = new DependencyHolder();
+
+ @Test
+ public void injectMocksWorks() {
+ assertNotNull(dependencyHolder.getFinalDemo());
+ }
+
+ @Test
+ public void testSay() throws Exception {
+
+ FinalDemo tested = dependencyHolder.getFinalDemo();
+
+ String expected = "Hello altered World";
+ when(tested.say("hello")).thenReturn("Hello altered World");
+
+ String actual = tested.say("hello");
+
+ assertEquals("Expected and actual did not match", expected, actual);
+
+ // Should still be mocked by now.
+ try {
+ verify(tested).say("world");
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertThat(e.getMessage(), is(containsString("Argument(s) are different! Wanted")));
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsTest.java
new file mode 100644
index 0000000..0b24102
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.junit.Assert.assertNull;
+import static org.mockito.Mockito.verify;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito and PowerMock
+ * annotations.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class MockFinalUsingAnnotationsTest {
+
+ @Mock
+ private FinalDemo usingMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.mockito.MockitoAnnotations.Mock
+ private FinalDemo usingDeprecatedMockitoMockAnnotation;
+
+ @SuppressWarnings("deprecation")
+ @org.powermock.core.classloader.annotations.Mock
+ private FinalDemo usingPowerMockMockAnnotation;
+
+ @Test
+ public void assertMockFinalWithMockitoMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingMockitoMockAnnotation.say(argument));
+
+ verify(usingMockitoMockAnnotation).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithDeprecatedMockitoMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingDeprecatedMockitoMockAnnotation.say(argument));
+
+ verify(usingDeprecatedMockitoMockAnnotation).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWhenUsingPowerMockMockAnnotationWorks() throws Exception {
+ final String argument = "hello";
+
+ assertNull(usingPowerMockMockAnnotation.say(argument));
+
+ verify(usingPowerMockMockAnnotation).say(argument);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsWithAnswersTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsWithAnswersTest.java
new file mode 100644
index 0000000..a595afc
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/MockFinalUsingAnnotationsWithAnswersTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito and PowerMock
+ * annotations using answers.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(FinalDemo.class)
+public class MockFinalUsingAnnotationsWithAnswersTest {
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private FinalDemo tested1;
+
+ @Mock(answer = Answers.RETURNS_MOCKS)
+ private FinalDemo tested2;
+
+ @Mock(answer = Answers.RETURNS_MOCKS, name = "myTested3")
+ private FinalDemo tested3;
+
+ @Test public void
+ assert_mock_final_with_mockito_mock_annotation_with_deep_stubs_works() {
+ when(tested1.simpleReturnExample().mySimpleMethod()).thenReturn(42);
+
+ assertEquals(42, tested1.simpleReturnExample().mySimpleMethod());
+ }
+
+ @Test public void
+ assert_mock_final_with_mockito_mock_annotation_with_returns_mocks_works() {
+ assertNotNull(tested2.simpleReturnExample());
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/SpyAnnotationTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/SpyAnnotationTest.java
new file mode 100644
index 0000000..91a4231
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/annotationbased/SpyAnnotationTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.annotationbased;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.PrivatePartialMockingExample;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.verifyPrivate;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ * Asserts that spying on private methods work with PowerMock when using
+ * {@link Spy} annotation.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PrivatePartialMockingExample.class)
+public class SpyAnnotationTest {
+
+ @Spy
+ private PrivatePartialMockingExample underTest = new PrivatePartialMockingExample();
+
+ @Test
+ public void spyingOnPrivateMethodsWorksWithSpyAnnotation() throws Exception {
+ final String expected = "TEST VALUE";
+ final String nameOfMethodToMock = "methodToMock";
+ final String input = "input";
+ when(underTest, nameOfMethodToMock, input).thenReturn(expected);
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verifyPrivate(underTest).invoke(nameOfMethodToMock, input);
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/argumentmatcher/ArgumentMatcherTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/argumentmatcher/ArgumentMatcherTest.java
new file mode 100644
index 0000000..66ddc0b
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/argumentmatcher/ArgumentMatcherTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.argumentmatcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.argumentmatcher.ArgumentMatcherDemo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.anyList;
+import static org.mockito.Matchers.eq;
+import static org.powermock.api.mockito.PowerMockito.doReturn;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+ at RunWith(PowerMockRunner.class)
+public class ArgumentMatcherTest {
+
+ @Test
+ public void worksWithArgumentMatchers() throws Exception {
+ final ArrayList<String> strings = new ArrayList<String>();
+
+ final ArgumentMatcherDemo tested = mock(ArgumentMatcherDemo.class);
+ doReturn(strings).when(tested, "findByNamedQuery", eq("AbstractPTVTicket.ticketSeatIds"), anyList());
+
+ final List<String> stringList = tested.findByNamedQuery("something", strings);
+ assertTrue(stringList.isEmpty());
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java
new file mode 100644
index 0000000..d52f8e0
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github510/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/510
+ */
+package samples.powermockito.junit4.bugs.github510;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ChildClass.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ChildClass.java
new file mode 100644
index 0000000..6c9faaf
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ChildClass.java
@@ -0,0 +1,20 @@
+package samples.powermockito.junit4.bugs.github583;
+
+/**
+ *
+ */
+public class ChildClass extends ParenClass {
+ private int b;
+ public ChildClass() {
+ super();
+ }
+ public int getB() {
+ return b;
+ }
+ public void setB(int b) {
+ this.b = b;
+ }
+ public void test(){
+
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ClassWithInheritanceTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ClassWithInheritanceTest.java
new file mode 100644
index 0000000..1b9eac2
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ClassWithInheritanceTest.java
@@ -0,0 +1,22 @@
+package samples.powermockito.junit4.bugs.github583;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Spy;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(value = {ChildClass.class})
+public class ClassWithInheritanceTest {
+ @Spy
+ ChildClass b = new ChildClass();
+
+ @Test
+ public void test_test(){
+ b.test();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ParenClass.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ParenClass.java
new file mode 100644
index 0000000..c090574
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/ParenClass.java
@@ -0,0 +1,14 @@
+package samples.powermockito.junit4.bugs.github583;
+
+/**
+ *
+ */
+public class ParenClass {
+ private int a;
+ public int getA() {
+ return a;
+ }
+ public void setA(int a) {
+ this.a = a;
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/package-info.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/package-info.java
new file mode 100644
index 0000000..f6c0402
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/bugs/github583/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * https://github.com/jayway/powermock/issues/583
+ */
+package samples.powermockito.junit4.bugs.github583;
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/constructor/InnerConstructorsAreFoundTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/constructor/InnerConstructorsAreFoundTest.java
new file mode 100644
index 0000000..ea10969
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/constructor/InnerConstructorsAreFoundTest.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.constructor;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+
+/**
+ * Asserts that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=267">issue 267</a>
+ * is resolved.
+ */
+ at PrepareForTest({ InnerConstructorsAreFoundTest.WorkingObjectUnderTesting.class,
+ InnerConstructorsAreFoundTest.BuggyObjectUnderTesting.class,
+ InnerConstructorsAreFoundTest.StillBuggyObjectUnderTesting.class })
+ at RunWith(PowerMockRunner.class)
+public class InnerConstructorsAreFoundTest {
+
+ interface AnyInterface {
+ };
+
+ class AnyImplementation implements AnyInterface {
+ @Override
+ public boolean equals(Object obj) {
+ return true;
+ }
+ }
+
+ class SomeOtherImplementationOfSomethingElse {
+ @Override
+ public boolean equals(Object obj) {
+ return true;
+ }
+ };
+
+ // <ObjectsUnderTesting>
+ class WorkingObjectUnderTesting {
+ void methodToTest() {
+ new WorkingObjectToMock(new AnyImplementation());
+ }
+ }
+
+ class BuggyObjectUnderTesting {
+ void methodToTest() {
+ new BuggyObjectToMock(new SomeOtherImplementationOfSomethingElse(), new AnyImplementation());
+ }
+ }
+
+ class StillBuggyObjectUnderTesting {
+ void methodToTest() {
+ new StillBuggyObjectToMock(new SomeOtherImplementationOfSomethingElse(),
+ new AnyInterface[] { new AnyImplementation() });
+ }
+ }
+
+ // </ObjectsUnderTesting>
+
+ // <ObjectsToMock>
+ class WorkingObjectToMock {
+ public WorkingObjectToMock(AnyInterface... anys) {
+ }
+ }
+
+ class BuggyObjectToMock {
+ @SuppressWarnings("unused")
+ private final AnyInterface[] anys;
+
+ public BuggyObjectToMock(SomeOtherImplementationOfSomethingElse other, AnyInterface... anys) {
+ this.anys = anys;
+ }
+ }
+
+ class StillBuggyObjectToMock {
+ @SuppressWarnings("unused")
+ private final AnyInterface[] anys;
+
+ public StillBuggyObjectToMock(SomeOtherImplementationOfSomethingElse other, AnyInterface[] anys) {
+ this.anys = anys;
+ }
+ }
+
+ @Mock
+ WorkingObjectToMock mockedWorkingObject;
+ @Mock
+ BuggyObjectToMock mockedBuggyObject;
+ @Mock
+ StillBuggyObjectToMock mockedStillBuggyObject;
+
+ @Test
+ public void shouldFindMemberVarArgsCtorWhenPassingArrayToWithArguments() throws Exception {
+ whenNew(BuggyObjectToMock.class).withArguments(new SomeOtherImplementationOfSomethingElse(),
+ (Object[]) new AnyInterface[] { new AnyImplementation() }).thenReturn(mockedBuggyObject);
+
+ new BuggyObjectUnderTesting().methodToTest();
+ }
+
+ @Test
+ public void shouldFindMemberArrayCtorWhenPassingArrayToWithArguments() throws Exception {
+ whenNew(StillBuggyObjectToMock.class).withArguments(new SomeOtherImplementationOfSomethingElse(),
+ (Object) new AnyInterface[] { new AnyImplementation() }).thenReturn(mockedStillBuggyObject);
+
+ new StillBuggyObjectUnderTesting().methodToTest();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/doreturn/DoReturnTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/doreturn/DoReturnTest.java
new file mode 100644
index 0000000..87cf785
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/doreturn/DoReturnTest.java
@@ -0,0 +1,52 @@
+package samples.powermockito.junit4.doreturn;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsEqual.equalTo;
+import static org.powermock.api.mockito.PowerMockito.doReturn;
+
+/**
+ * Created by gauee on 12/11/15.
+ * Test that demonstrates that <a
+ * href="https://github.com/jayway/powermock/issues/599">issue 599</a>
+ * is resolved.
+ */
+ at RunWith(PowerMockRunner.class)
+public class DoReturnTest {
+
+ private static final String TEMP_DAY_FIRST = "41F";
+ private static final String TEMP_DAY_SECOND = "44F";
+
+ @Mock
+ private Weather weather;
+
+ interface Weather {
+ String getTemperature();
+ }
+
+ @Before
+ public void init() {
+ doReturn(TEMP_DAY_FIRST, TEMP_DAY_SECOND).when(weather).getTemperature();
+ }
+
+ @Test
+ public void returnsDifferentTemperatureForEachInvocation(){
+ assertThat(weather.getTemperature(), is(equalTo(TEMP_DAY_FIRST)));
+ assertThat(weather.getTemperature(), is(equalTo(TEMP_DAY_SECOND)));
+ }
+
+ @Test
+ public void returnsFirstTemperatureWhenPassedArrayIsEmpty() {
+ doReturn(TEMP_DAY_FIRST, new Object[0]).when(weather).getTemperature();
+
+ assertThat(weather.getTemperature(), is(equalTo(TEMP_DAY_FIRST)));
+ assertThat(weather.getTemperature(), is(equalTo(TEMP_DAY_FIRST)));
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/enums/EnumWithConstructorTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/enums/EnumWithConstructorTest.java
new file mode 100644
index 0000000..9c16468
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/enums/EnumWithConstructorTest.java
@@ -0,0 +1,36 @@
+package samples.powermockito.junit4.enums;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.enummocking.EnumWithConstructor;
+import samples.enummocking.SomeObjectInterfaceImpl;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.sameInstance;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(value = {EnumWithConstructor.class, SomeObjectInterfaceImpl.class}, fullyQualifiedNames = "samples.enummocking.EnumWithConstructor$1")
+public class EnumWithConstructorTest {
+
+ @Mock(name = "expectedSomeObjectInterfaceImpl")
+ private SomeObjectInterfaceImpl someImplMock;
+
+ @Test
+ public void testCallMethodWithConstructor() throws Exception {
+
+ whenNew(SomeObjectInterfaceImpl.class).withNoArguments().thenReturn(someImplMock);
+
+ SomeObjectInterfaceImpl actual = (SomeObjectInterfaceImpl) EnumWithConstructor.SOME_ENUM_VALUE.create();
+
+ assertThat(actual, is(sameInstance(someImplMock)));
+
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/equalsmocking/EqualsMockingTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/equalsmocking/EqualsMockingTest.java
new file mode 100644
index 0000000..2876458
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/equalsmocking/EqualsMockingTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.equalsmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import javax.naming.InitialContext;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(InitialContext.class)
+public class EqualsMockingTest {
+
+ @Test
+ public void shouldStubEquals() throws Exception {
+ stub(method(InitialContext.class, "equals")).toReturn(true);
+ final InitialContext context = new InitialContext();
+
+ assertTrue(context.equals(new Object()));
+ }
+
+ @Test
+ public void shouldMockEquals() throws Exception {
+ Object object = new Object();
+
+ final InitialContext context = mock(InitialContext.class);
+ when(context.equals(object)).thenReturn(true);
+
+ assertTrue(context.equals(object));
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/finalmocking/FinalDemoTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/finalmocking/FinalDemoTest.java
new file mode 100644
index 0000000..1308d8a
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/finalmocking/FinalDemoTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.finalmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+import samples.privateandfinal.PrivateFinal;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Test class to demonstrate non-static final mocking with Mockito.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { FinalDemo.class, PrivateFinal.class })
+public class FinalDemoTest {
+
+ @Test
+ public void assertMockFinalWithNoExpectationsWorks() throws Exception {
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ assertNull(tested.say(argument));
+
+ verify(tested).say(argument);
+ }
+
+ @Test
+ public void assertMockFinalWithExpectationsWorks() throws Exception {
+ final String argument = "hello";
+ final String expected = "Hello altered World";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.say(argument)).thenReturn(expected);
+
+ final String actual = tested.say(argument);
+
+ verify(tested).say(argument);
+
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertFinalNativeWithExpectationsWorks() throws Exception {
+ final String expected = "Hello altered World";
+ final String argument = "hello";
+
+ FinalDemo tested = mock(FinalDemo.class);
+
+ when(tested.sayFinalNative(argument)).thenReturn("Hello altered World");
+
+ String actual = tested.sayFinalNative(argument);
+
+ verify(tested).sayFinalNative(argument);
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void assertSpyingOnFinalInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ final String argument = "PowerMock";
+ final String expected = "something";
+
+ assertEquals("Hello " + argument, spy.say(argument));
+ when(spy.say(argument)).thenReturn(expected);
+ assertEquals(expected, spy.say(argument));
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void assertSpyingOnFinalVoidInstanceMethodWorks() throws Exception {
+ FinalDemo tested = new FinalDemo();
+ FinalDemo spy = spy(tested);
+
+ doThrow(new ArrayStoreException()).when(spy).finalVoidCallee();
+
+ spy.finalVoidCaller();
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorks() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ when(spy, "sayIt", isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke("sayIt", expected);
+ }
+
+ @Test
+ public void assertSpyingOnPrivateFinalInstanceMethodWorksWhenUsingJavaLangReflectMethod() throws Exception {
+ PrivateFinal spy = spy(new PrivateFinal());
+
+ final String expected = "test";
+ assertEquals("Hello " + expected, spy.say(expected));
+
+ final Method methodToExpect = method(PrivateFinal.class, "sayIt");
+ when(spy, methodToExpect).withArguments(isA(String.class)).thenReturn(expected);
+
+ assertEquals(expected, spy.say(expected));
+
+ verifyPrivate(spy, times(2)).invoke(methodToExpect).withArguments(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/getclass/GetClassTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/getclass/GetClassTest.java
new file mode 100644
index 0000000..1a917c0
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/getclass/GetClassTest.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.getclass;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.MockGateway;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+
+import static org.junit.Assert.*;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+/**
+ * Assert that "getClass" on an object works correctly on objects
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ExpectNewDemo.class)
+public class GetClassTest {
+
+ @Test
+ public void getClassReturnsTheCorrectClassForNewInstancesOfClassesPrepareForTest() throws Exception {
+ ExpectNewDemo instance = new ExpectNewDemo();
+ assertEquals(ExpectNewDemo.class, instance.getClass());
+ }
+
+ @Test
+ public void getClassReturnsTheCorrectClassForMocksPrepareForTest() throws Exception {
+ ExpectNewDemo instance = mock(ExpectNewDemo.class);
+ assertNotNull(instance.getClass());
+ }
+
+ @Test
+ public void getClassReturnsNullForMocksPreparedForTestWhenMockingOfGetClassAllowed() throws Exception {
+ MockGateway.MOCK_GET_CLASS_METHOD = true;
+ ExpectNewDemo instance = mock(ExpectNewDemo.class);
+ try {
+ assertNull(instance.getClass());
+ } finally {
+ // Make sure we reset to the default for subsequent tests.
+ MockGateway.MOCK_GET_CLASS_METHOD = false;
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/HashCodeTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/HashCodeTest.java
new file mode 100644
index 0000000..a530cf8
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/HashCodeTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.hashcode;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import javax.naming.InitialContext;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(InitialContext.class)
+public class HashCodeTest {
+ private final static int EXPECTED_HASH = 12316;
+
+ @Test
+ public void shouldStubHashCode() throws Exception {
+ stub(method(InitialContext.class, "hashCode")).toReturn(EXPECTED_HASH);
+ final InitialContext context = new InitialContext();
+
+ assertEquals(EXPECTED_HASH, context.hashCode());
+ }
+
+ @Test
+ public void shouldMockHashCode() throws Exception {
+ InitialContext context = mock(InitialContext.class);
+ when(context.hashCode()).thenReturn(EXPECTED_HASH);
+
+ assertEquals(EXPECTED_HASH, context.hashCode());
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/InnerClassHashCodeTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/InnerClassHashCodeTest.java
new file mode 100644
index 0000000..d160241
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/hashcode/InnerClassHashCodeTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.hashcode;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.HashMap;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.stub;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({InnerClassHashCodeTest.SubHashMap.class})
+public class InnerClassHashCodeTest {
+
+ private static final int EXPECTED_HASH = 123456;
+
+ @Test
+ @Ignore("This should work but it's a bug")
+ public void can_mock_inner_hash_code_method() {
+ SubHashMap actor = mock(SubHashMap.class);
+ when(actor.hashCode()).thenReturn(EXPECTED_HASH);
+
+ int hashCode = actor.hashCode();
+
+ assertThat(hashCode, equalTo(EXPECTED_HASH));
+ }
+
+ @Test
+ public void can_stub_inner_hash_code_method() {
+ stub(method(SubHashMap.class, "hashCode")).toReturn(EXPECTED_HASH);
+ SubHashMap actor = new SubHashMap();
+
+ int hashCode = actor.hashCode();
+
+ assertThat(hashCode, equalTo(123456));
+ }
+
+ public class SubHashMap extends HashMap {
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o);
+ }
+ }
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/largemethod/LargeMethodTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/largemethod/LargeMethodTest.java
new file mode 100644
index 0000000..3da89c5
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/largemethod/LargeMethodTest.java
@@ -0,0 +1,56 @@
+package samples.powermockito.junit4.largemethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.largemethod.MethodExceedingJvmLimit;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(MethodExceedingJvmLimit.class)
+public class LargeMethodTest {
+
+ @Test
+ public void largeMethodShouldBeOverridden() {
+ try {
+ MethodExceedingJvmLimit.init();
+ fail("Method should be overridden and exception should be thrown");
+ } catch (Exception e) {
+ assertSame(IllegalAccessException.class, e.getClass());
+ assertTrue(e.getMessage().contains("Method was too large and after instrumentation exceeded JVM limit"));
+ }
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeSuppressed() {
+ suppress(PowerMockito.method(MethodExceedingJvmLimit.class, "init"));
+ assertNull("Suppressed method should return: null", MethodExceedingJvmLimit.init());
+ }
+
+ @Test
+ public void largeMethodShouldBeAbleToBeMocked() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ when(MethodExceedingJvmLimit.init()).thenReturn("ok");
+ assertEquals("Mocked method should return: ok", "ok", MethodExceedingJvmLimit.init());
+ verifyStatic();
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void largeMethodShouldBeAbleToBeMockedAndThrowException() {
+ mockStatic(MethodExceedingJvmLimit.class);
+ when(MethodExceedingJvmLimit.init()).thenThrow(new IllegalStateException());
+ MethodExceedingJvmLimit.init();
+ verifyStatic();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/membermodification/MemberModificationExampleTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/membermodification/MemberModificationExampleTest.java
new file mode 100644
index 0000000..7dcf02e
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/membermodification/MemberModificationExampleTest.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.membermodification;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+import samples.suppressconstructor.SuppressConstructorHierarchy;
+import samples.suppresseverything.SuppressEverything;
+import samples.suppressfield.SuppressField;
+import samples.suppressmethod.SuppressMethod;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructorsDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberMatcher.everythingDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberMatcher.field;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberMatcher.methods;
+import static org.powermock.api.support.membermodification.MemberMatcher.methodsDeclaredIn;
+import static org.powermock.api.support.membermodification.MemberModifier.*;
+
+/**
+ * Demonstrates PowerMock's ability to modify member structures.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { SuppressMethod.class, SuppressField.class, SuppressEverything.class })
+public class MemberModificationExampleTest {
+
+ @Test
+ public void suppressSingleMethodExample() throws Exception {
+ suppress(method(SuppressMethod.class, "getObject"));
+
+ assertNull(new SuppressMethod().getObject());
+ }
+
+ @Test
+ public void suppressMultipleMethodsExample1() throws Exception {
+ suppress(methods(SuppressMethod.class, "getObject", "getInt"));
+
+ assertNull(new SuppressMethod().getObject());
+ assertEquals(0, new SuppressMethod().getInt());
+ }
+
+ @Test
+ public void suppressMultipleMethodsExample2() throws Exception {
+ suppress(methods(method(SuppressMethod.class, "getObject"), method(SuppressMethod.class, "getInt")));
+
+ assertNull(new SuppressMethod().getObject());
+ assertEquals(0, new SuppressMethod().getInt());
+ }
+
+ @Test
+ public void suppressAllMethodsExample() throws Exception {
+ suppress(methodsDeclaredIn(SuppressMethod.class));
+
+ final SuppressMethod tested = new SuppressMethod();
+
+ assertNull(tested.getObject());
+ assertNull(SuppressMethod.getObjectStatic());
+ assertEquals(0, tested.getByte());
+ }
+
+ @Test
+ public void suppressSingleFieldExample() throws Exception {
+ suppress(field(SuppressField.class, "domainObject"));
+
+ SuppressField tested = new SuppressField();
+ assertNull(tested.getDomainObject());
+ }
+
+ @Test
+ public void suppressConstructorExample() throws Exception {
+ suppress(constructor(SuppressConstructorHierarchy.class));
+
+ SuppressConstructorHierarchy tested = new SuppressConstructorHierarchy("message");
+
+ assertEquals(42, tested.getNumber());
+ assertNull(tested.getMessage());
+ }
+
+ @Test
+ public void stubSingleMethodExample() throws Exception {
+ final String expectedReturnValue = "new";
+ stub(method(SuppressMethod.class, "getObject")).toReturn(expectedReturnValue);
+
+ final SuppressMethod tested = new SuppressMethod();
+ assertEquals(expectedReturnValue, tested.getObject());
+ assertEquals(expectedReturnValue, tested.getObject());
+ }
+
+ @Test
+ public void duckTypeStaticMethodExample() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "getStaticMessage"));
+
+ assertEquals(SuppressMethod.getObjectStatic(), StaticAndInstanceDemo.getStaticMessage());
+ }
+
+ @Test
+ public void whenReplacingMethodWithAMethodOfIncorrectReturnTypeThenAnIAEIsThrown() throws Exception {
+ try {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "aVoidMethod"));
+ fail("Should thow IAE");
+ } catch (Exception e) {
+ assertEquals("The replacing method (public static void samples.staticandinstance.StaticAndInstanceDemo.aVoidMethod()) needs to return java.lang.Object and not void.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void whenReplacingMethodWithAMethodOfWithIncorrectParametersThenAnIAEIsThrown() throws Exception {
+ try {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(
+ method(StaticAndInstanceDemo.class, "aMethod2"));
+ fail("Should thow IAE");
+ } catch (Exception e) {
+ assertEquals("The replacing method, \"public static java.lang.Object samples.staticandinstance.StaticAndInstanceDemo.aMethod2(java.lang.String)\", needs to have the same number of parameters of the same type as as method \"public static java.lang.Object samples.suppressmethod.SuppressMethod.getObjectStatic()\".", e.getMessage());
+ }
+ }
+
+ @Test
+ public void changingReturnValueExample() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectWithArgument")).with(new ReturnValueChangingInvocationHandler());
+
+ final SuppressMethod tested = new SuppressMethod();
+
+ assertThat(tested.getObjectWithArgument("don't do anything"), is(instanceOf(Object.class)));
+ assertEquals("hello world", tested.getObjectWithArgument("make it a string"));
+ }
+
+ @Test
+ public void suppressAllConstructors() throws Exception {
+ suppress(constructorsDeclaredIn(SuppressEverything.class));
+
+ SuppressEverything suppressEverything = new SuppressEverything();
+ new SuppressEverything("test");
+
+ try {
+ suppressEverything.something();
+ fail("Should throw ISE");
+ } catch (IllegalStateException e) {
+ assertEquals("error", e.getMessage());
+ }
+ }
+
+ @Test
+ public void suppressEverythingExample() throws Exception {
+ suppress(everythingDeclaredIn(SuppressEverything.class));
+
+ SuppressEverything suppressEverything = new SuppressEverything();
+ new SuppressEverything("test");
+ suppressEverything.something();
+ suppressEverything.somethingElse();
+ }
+
+ private final class ReturnValueChangingInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object object, Method method, Object[] arguments) throws Throwable {
+ if (arguments[0].equals("make it a string")) {
+ return "hello world";
+ } else {
+ return method.invoke(object, arguments);
+ }
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/nested/NestedClassDefinedInsideTestCaseTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/nested/NestedClassDefinedInsideTestCaseTest.java
new file mode 100644
index 0000000..4944521
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/nested/NestedClassDefinedInsideTestCaseTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.nested;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { NestedClassDefinedInsideTestCaseTest.class })
+public class NestedClassDefinedInsideTestCaseTest {
+
+ @Test
+ public void mocksNestedPrivateClassDefinedInsideTestCase() throws Exception {
+ NestedPrivateClassDefinedInsideTestCase tested = mock(NestedPrivateClassDefinedInsideTestCase.class);
+ when(tested.getValue()).thenReturn("something");
+
+ assertEquals("something", tested.getValue());
+ }
+
+ @Test
+ @Ignore("See issue 95")
+ public void mocksNestedPrivateFinalClassDefinedInsideTestCase() throws Exception {
+ NestedPrivateFinalClassDefinedInsideTestCase tested = mock(NestedPrivateFinalClassDefinedInsideTestCase.class);
+ when(tested.getValue()).thenReturn("something");
+
+ assertEquals("something", tested.getValue());
+ }
+
+ private class NestedPrivateClassDefinedInsideTestCase {
+ public String getValue() {
+ return "value";
+ }
+ }
+
+ private final class NestedPrivateFinalClassDefinedInsideTestCase {
+ public String getValue() {
+ return "value";
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingExampleTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingExampleTest.java
new file mode 100644
index 0000000..79903b7
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingExampleTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.PartialMockingExample;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.doReturn;
+import static org.powermock.api.mockito.PowerMockito.spy;
+
+/**
+ * Asserts that partial mocking (spying) with PowerMockito works for non-final
+ * methods.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PartialMockingExample.class)
+public class PartialMockingExampleTest {
+
+ @Test
+ public void validatingSpiedObjectGivesCorrectNumberOfExpectedInvocations() throws Exception {
+ final String expected = "TEST VALUE";
+ PartialMockingExample underTest = spy(new PartialMockingExample());
+ doReturn(expected).when(underTest).methodToMock();
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verify(underTest).methodToMock();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingRetainsStateTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingRetainsStateTest.java
new file mode 100644
index 0000000..8777389
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PartialMockingRetainsStateTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.MockSelfDemo;
+import samples.partialmocking.MockWithStaticStateDemo;
+
+import static junit.framework.Assert.assertEquals;
+
+/**
+ * Demonstrates that PowerMockito retains state when spying. This was previously
+ * a bug (issue <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=263">263</a>).
+ */
+ at RunWith(PowerMockRunner.class)
+public class PartialMockingRetainsStateTest {
+
+ @Test
+ public void spyingOnAnObjectRetainsState() throws Exception {
+ MockSelfDemo demo = new MockSelfDemo(4);
+ MockSelfDemo spy = PowerMockito.spy(demo);
+ assertEquals(4, spy.getConstructorValue());
+ }
+
+ @Test
+ public void spyingOnAClassRetainsState() throws Exception {
+ PowerMockito.spy(MockWithStaticStateDemo.class);
+ assertEquals(5, MockWithStaticStateDemo.getState());
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PrivatePartialMockingExampleTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PrivatePartialMockingExampleTest.java
new file mode 100644
index 0000000..3dcb8f8
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/PrivatePartialMockingExampleTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.PrivatePartialMockingExample;
+
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Asserts that partial mocking (spying) with PowerMockito works for non-final
+ * private methods.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(PrivatePartialMockingExample.class)
+public class PrivatePartialMockingExampleTest {
+
+ @Test
+ public void spyingOnPrivateMethodsWorks() throws Exception {
+ final String expected = "TEST VALUE";
+ PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());
+ final String nameOfMethodToMock = "methodToMock";
+ final String input = "input";
+ when(underTest, nameOfMethodToMock, input).thenReturn(expected);
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verifyPrivate(underTest).invoke(nameOfMethodToMock, input);
+ }
+
+ @Test
+ public void partialMockingOfPrivateMethodsWorks() throws Exception {
+ final String expected = "TEST VALUE";
+ PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());
+ final String nameOfMethodToMock = "methodToMock";
+ final String input = "input";
+ doReturn(expected).when(underTest, nameOfMethodToMock, input);
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verifyPrivate(underTest).invoke(nameOfMethodToMock, input);
+ }
+
+ @Test
+ public void spyingOnPrivateMethodsWorksWithoutSpecifyingMethodName() throws Exception {
+ final String expected = "TEST VALUE";
+ PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());
+ final String input = "input";
+ final Method methodToMock = method(PrivatePartialMockingExample.class, String.class);
+ when(underTest, methodToMock).withArguments(input).thenReturn(expected);
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verifyPrivate(underTest).invoke(methodToMock).withArguments(input);
+ }
+
+ @Test
+ public void partialMockingOfPrivateMethodsWorksWithoutSpecifyingMethodName() throws Exception {
+ final String expected = "TEST VALUE";
+ PrivatePartialMockingExample underTest = spy(new PrivatePartialMockingExample());
+ final String input = "input";
+ final Method methodToMock = method(PrivatePartialMockingExample.class, String.class);
+ doReturn(expected).when(underTest, methodToMock).withArguments(input);
+
+ assertEquals(expected, underTest.methodToTest());
+
+ verifyPrivate(underTest).invoke(methodToMock).withArguments(input);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/StaticPartialMockingTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/StaticPartialMockingTest.java
new file mode 100644
index 0000000..59f2b10
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/partialmocking/StaticPartialMockingTest.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.partialmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.partialmocking.MockSelfDemo;
+import samples.singleton.StaticExample;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({StaticExample.class, MockSelfDemo.class})
+public class StaticPartialMockingTest {
+
+ @Test
+ public void spyingOnStaticMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ assertTrue(Object.class.equals(StaticExample.objectMethod().getClass()));
+ when(StaticExample.class, "privateObjectMethod").thenReturn("Hello static");
+
+ assertEquals("Hello static", StaticExample.objectMethod());
+ /*
+ * privateObjectMethod should be invoked twice, once at "assertTrue" and
+ * once above.
+ */
+ verifyPrivate(StaticExample.class, times(2)).invoke("privateObjectMethod");
+ }
+
+ @Test
+ public void partialMockingOfStaticMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ assertTrue(Object.class.equals(StaticExample.objectMethod().getClass()));
+ doReturn("Hello static").when(StaticExample.class, "privateObjectMethod");
+
+ assertEquals("Hello static", StaticExample.objectMethod());
+ /*
+ * privateObjectMethod should be invoked twice, once at "assertTrue" and
+ * once above.
+ */
+ verifyPrivate(StaticExample.class, times(2)).invoke("privateObjectMethod");
+ }
+
+ @Test
+ public void partialPrivateMockingWithAnswerOfStaticMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ assertTrue(Object.class.equals(StaticExample.objectMethod().getClass()));
+ doAnswer(new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ return "Hello static";
+ }
+ }).when(StaticExample.class, "privateObjectMethod");
+
+ assertEquals("Hello static", StaticExample.objectMethod());
+ /*
+ * privateObjectMethod should be invoked twice, once at "assertTrue" and
+ * once above.
+ */
+ verifyPrivate(StaticExample.class, times(2)).invoke("privateObjectMethod");
+ }
+
+ @Test
+ public void spyingOnStaticFinalMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ assertTrue(Object.class.equals(StaticExample.objectFinalMethod().getClass()));
+
+ when(StaticExample.class, "privateObjectFinalMethod").thenReturn("Hello static");
+
+ assertEquals("Hello static", StaticExample.objectFinalMethod());
+
+ verifyPrivate(StaticExample.class, times(2)).invoke("privateObjectFinalMethod");
+ }
+
+ @Test
+ public void partialMockingOfStaticFinalMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ assertTrue(Object.class.equals(StaticExample.objectFinalMethod().getClass()));
+
+ doReturn("Hello static").when(StaticExample.class, "privateObjectFinalMethod");
+
+ assertEquals("Hello static", StaticExample.objectFinalMethod());
+
+ verifyPrivate(StaticExample.class, times(2)).invoke("privateObjectFinalMethod");
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void spyingOnStaticVoidMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ StaticExample.voidMethod();
+
+ when(StaticExample.class, "privateVoidMethod").thenThrow(new ArrayStoreException());
+ StaticExample.voidMethod();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void partialMockingOfStaticVoidMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ StaticExample.voidMethod();
+
+ doThrow(new ArrayStoreException()).when(StaticExample.class, "privateVoidMethod");
+ StaticExample.voidMethod();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void spyingOnStaticFinalVoidMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ StaticExample.voidFinalMethod();
+
+ when(StaticExample.class, "privateVoidFinalMethod").thenThrow(new ArrayStoreException());
+ StaticExample.voidFinalMethod();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void partialMockingOfStaticFinalVoidMethodReturningObjectWorks() throws Exception {
+ spy(StaticExample.class);
+
+ StaticExample.voidFinalMethod();
+
+ doThrow(new ArrayStoreException()).when(StaticExample.class, "privateVoidFinalMethod");
+ StaticExample.voidFinalMethod();
+ }
+
+ @Test
+ public void partialMockingOfPublicStaticVoidWorks() throws Exception {
+ spy(StaticExample.class);
+
+ // Given
+ doNothing().when(StaticExample.class);
+ StaticExample.staticVoidMethod();
+
+ // When
+ StaticExample.staticVoidMethod();
+
+ // Then
+ verifyStatic(times(1));
+ StaticExample.staticVoidMethod();
+ }
+
+ @Test
+ public void partialMockingOfPublicStaticFinalVoidWorks() throws Exception {
+ spy(StaticExample.class);
+
+ doNothing().when(StaticExample.class);
+ StaticExample.staticFinalVoidMethod();
+
+ StaticExample.staticFinalVoidMethod();
+ }
+
+ @Test
+ public void partialMockingOfNonVoidPublicStaticMethodsWorks() throws Exception {
+ spy(StaticExample.class);
+
+ doReturn("something").when(StaticExample.class);
+ StaticExample.staticMethodReturningString();
+
+ assertEquals("something", StaticExample.staticMethodReturningString());
+ }
+
+ @Test
+ public void partialMockingWithAnswerOfNonVoidPublicStaticMethodsWorks() throws Exception {
+ spy(StaticExample.class);
+
+ doAnswer(new Answer<String>() {
+ @Override
+ public String answer(InvocationOnMock invocation) throws Throwable {
+ return "something";
+ }
+ }).when(StaticExample.class);
+ StaticExample.staticMethodReturningString();
+
+ assertEquals("something", StaticExample.staticMethodReturningString());
+ }
+
+ @Test
+ public void partialMockingOfPublicStaticMethodsWorks() throws Exception {
+ spy(MockSelfDemo.class);
+ when(MockSelfDemo.class, method(MockSelfDemo.class, "methodToBeStubbed")).withNoArguments().thenReturn(2);
+
+ int result = MockSelfDemo.getSomething();
+ assertEquals(4, result);
+ }
+
+ @Test
+ public void partialMockingOfPublicStaticMethodsWorksWhenUsingDoReturn() throws Exception {
+ spy(MockSelfDemo.class);
+
+ doReturn(2).when(MockSelfDemo.class);
+ MockSelfDemo.methodToBeStubbed();
+
+ int result = MockSelfDemo.getSomething();
+ assertEquals(4, result);
+ }
+
+ @Test
+ public void partialMockingOfPublicStaticMethodsWorksWhenUsingDoReturnAndMethodNameAsString() throws Exception {
+ spy(MockSelfDemo.class);
+
+ doReturn(3).when(MockSelfDemo.class, "methodToBeStubbed");
+
+ int result = MockSelfDemo.getSomething();
+ assertEquals(6, result);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/privatemocking/PrivateInstanceMockingTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/privatemocking/PrivateInstanceMockingTest.java
new file mode 100644
index 0000000..f84407a
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/privatemocking/PrivateInstanceMockingTest.java
@@ -0,0 +1,166 @@
+package samples.powermockito.junit4.privatemocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.privateandfinal.PrivateFinal;
+import samples.privatemocking.PrivateMethodDemo;
+
+import javax.activation.FileDataSource;
+import java.io.File;
+import java.io.StringReader;
+
+import static org.junit.Assert.*;
+import static org.mockito.Matchers.isA;
+import static org.mockito.Mockito.never;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({PrivateMethodDemo.class})
+public class PrivateInstanceMockingTest {
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", 12, "test").thenReturn("another");
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ }
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethodsUsingDoReturn() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ doReturn("another").when(tested, "doSayYear", 12, "test");
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ }
+
+ @Test
+ public void expectationsWorkWhenSpyingOnPrivateMethodsUsingDoReturnWhenMethodDoesntHaveAnyArguments() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ doReturn("another").when(tested, "sayIt");
+
+ assertEquals("another", Whitebox.invokeMethod(tested, "sayIt"));
+
+ verifyPrivate(tested).invoke("sayIt");
+ }
+
+ @Test
+ public void verifyPrivateMethodWhenNoExpectationForTheMethodHasBeenMade() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ assertEquals("Hello Johan, you are 29 old.", tested.sayYear("Johan", 29));
+
+ verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
+ }
+
+ @Test
+ public void expectationsWorkWithArgumentMatchersWhenSpyingOnPrivateMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ verifyPrivate(tested).invoke("doSayYear", 29, "Johan");
+ verifyPrivate(tested).invoke("doSayYear", 12, "test");
+ verifyPrivate(tested).invoke("doSayYear", 50, "Temp");
+ }
+
+ @Test
+ public void errorousVerificationOnPrivateMethodGivesFilteredErrorMessage() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+ assertEquals("Hello Temp, you are 50 old.", tested.sayYear("Temp", 50));
+
+ when(tested, "doSayYear", Mockito.anyInt(), Mockito.anyString()).thenReturn("another");
+
+ assertEquals("another", tested.sayYear("Johan", 29));
+ assertEquals("another", tested.sayYear("test", 12));
+
+ try {
+ verifyPrivate(tested, never()).invoke("doSayYear", 50, "Temp");
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.privatemocking.PrivateMethodDemo.doSayYear(\n 50,\n \"Temp\"\n);\nNever wanted but invoked .", e
+ .getMessage());
+ }
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectationsWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(Object.class)).thenThrow(new ArrayStoreException());
+
+ tested.doObjectStuff(new Object());
+ }
+
+ @Test
+ public void answersWorkWhenSpyingOnPrivateVoidMethods() throws Exception {
+ PrivateMethodDemo tested = spy(new PrivateMethodDemo());
+
+ tested.doObjectStuff(new Object());
+
+ when(tested, "doObjectInternal", isA(String.class)).thenAnswer(new Answer<Void>() {
+ private static final long serialVersionUID = 20645008237481667L;
+
+ @Override
+ public Void answer(InvocationOnMock invocation) throws Throwable {
+ assertEquals("Testing", invocation.getArguments()[0]);
+ return null;
+ }
+ });
+ tested.doObjectStuff(new Object());
+ tested.doObjectStuff("Testing");
+ }
+
+ @Test
+ public void spyingOnPrivateFinalMethodsWorksWhenClassIsNotFinal() throws Exception {
+ PrivateFinal tested = spy(new PrivateFinal());
+
+ final String name = "test";
+ tested.say(name);
+ assertEquals("Hello " + name, tested.say(name));
+
+ when(tested, "sayIt", name).thenReturn("First", "Second");
+
+ assertEquals("First", tested.say(name));
+ assertEquals("Second", tested.say(name));
+ }
+
+ @Test
+ public void usingMultipleArgumentsOnPrivateMethodWorks() throws Exception {
+ File file = mock(File.class);
+ FileDataSource fileDataSource = mock(FileDataSource.class);
+ StringReader expected = new StringReader("Some string");
+
+ PrivateMethodDemo tested = mock(PrivateMethodDemo.class);
+ doReturn(expected).when(tested, method(PrivateMethodDemo.class, "createReader", File.class, FileDataSource.class)).withArguments(file, fileDataSource);
+
+ StringReader actual = Whitebox.invokeMethod(tested, "createReader", file, fileDataSource);
+
+ assertSame(expected, actual);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/proxymethod/ProxyMethodTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/proxymethod/ProxyMethodTest.java
new file mode 100644
index 0000000..0eca76c
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/proxymethod/ProxyMethodTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.proxymethod;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.suppressmethod.SuppressMethod;
+import samples.suppressmethod.SuppressMethodExample;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.replace;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(SuppressMethod.class)
+public class ProxyMethodTest {
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectionThrowingMethodProxyWorksForJavaLangReflectMethods() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(new ThrowingInvocationHandler());
+
+ new SuppressMethod().getObject();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void expectionThrowingMethodProxyWorksForMethodNames() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(new ThrowingInvocationHandler());
+
+ new SuppressMethod().getObject();
+ }
+
+ @Test
+ public void returnValueChangingMethodProxyWorksForMethodNames() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(new ReturnValueChangingInvocationHandler());
+
+ assertEquals("hello world", new SuppressMethod().getObject());
+ }
+
+ @Test
+ public void delegatingMethodProxyWorksForMethodNames() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(new DelegatingInvocationHandler());
+
+ assertSame(SuppressMethod.OBJECT, new SuppressMethod().getObject());
+ }
+
+ @Test
+ public void mockingAndMethodProxyAtTheSameTimeWorks() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(new DelegatingInvocationHandler());
+ SuppressMethod tested = mock(SuppressMethod.class);
+
+ when(tested.getObject()).thenReturn("Hello world");
+
+ assertSame(SuppressMethod.OBJECT, SuppressMethod.getObjectStatic());
+
+ assertEquals("Hello world", tested.getObject());
+
+ verify(tested).getObject();
+ }
+
+ @Test
+ @Ignore("Doesn't work atm")
+ public void replaceInstanceMethodsWork() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(method(SuppressMethodExample.class, "getStringObject"));
+ SuppressMethod tested = new SuppressMethod();
+ assertEquals("test", tested.getObject());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void replaceInstanceMethodToStaticMethodDoesntWork() throws Exception {
+ replace(method(SuppressMethod.class, "getObject")).with(method(SuppressMethodExample.class, "getStringObjectStatic"));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void replaceStaticMethodToInstaceMethodDoesntWork() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(method(SuppressMethodExample.class, "getStringObject"));
+ }
+
+
+ @Test
+ public void replaceStaticMethodsWork() throws Exception {
+ replace(method(SuppressMethod.class, "getObjectStatic")).with(method(SuppressMethodExample.class, "getStringObjectStatic"));
+ assertEquals("test", SuppressMethod.getObjectStatic());
+ }
+
+ private final class ThrowingInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object object, Method method, Object[] arguments) throws Throwable {
+ throw new ArrayStoreException();
+ }
+ }
+
+ private final class ReturnValueChangingInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object object, Method method, Object[] arguments) throws Throwable {
+ return "hello world";
+ }
+ }
+
+ private final class DelegatingInvocationHandler implements InvocationHandler {
+ @Override
+ public Object invoke(Object object, Method method, Object[] arguments) throws Throwable {
+ return method.invoke(object, arguments);
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/simplemix/SimpleMixTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/simplemix/SimpleMixTest.java
new file mode 100644
index 0000000..3db19e3
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/simplemix/SimpleMixTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.simplemix;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PowerMockListener;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.core.testlisteners.FieldDefaulter;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import samples.simplemix.SimpleMix;
+import samples.simplemix.SimpleMixCollaborator;
+import samples.simplemix.SimpleMixConstruction;
+import samples.simplemix.SimpleMixUtilities;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+
+/**
+ * Demonstrates PowerMockito features such as static mocking, final mocking,
+ * partial mocking and setting internal state. It also demonstrates
+ * test-chunking and final system class mocking.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PowerMockListener(FieldDefaulter.class)
+public class SimpleMixTest {
+
+ @PrepareForTest( { SimpleMixUtilities.class, SimpleMixCollaborator.class, SimpleMix.class })
+ @Test
+ public void staticPartialFinalMocking() throws Exception {
+ SimpleMix tested = spy(new SimpleMix());
+
+ when(tested, "getValue").thenReturn(0);
+ SimpleMixCollaborator simpleMixCollaboratorMock = mock(SimpleMixCollaborator.class);
+ mockStatic(SimpleMixUtilities.class);
+ SimpleMixConstruction simpleMixConstructionMock = mock(SimpleMixConstruction.class);
+
+ Whitebox.setInternalState(tested, simpleMixCollaboratorMock);
+
+ when(SimpleMixUtilities.getRandomInteger()).thenReturn(10);
+ when(simpleMixCollaboratorMock.getRandomInteger()).thenReturn(6);
+ whenNew(SimpleMixConstruction.class).withNoArguments().thenReturn(simpleMixConstructionMock);
+ when(simpleMixConstructionMock.getMyValue()).thenReturn(1);
+
+ assertEquals(4, tested.calculate());
+
+ verifyStatic();
+ SimpleMixUtilities.getRandomInteger();
+ verifyNew(SimpleMixConstruction.class).withNoArguments();
+ verifyPrivate(tested).invoke(method(SimpleMix.class, "getValue"));
+ }
+
+ @PrepareForTest( { SimpleMix.class })
+ @Test
+ public void finalSystemClassMocking() throws Exception {
+ SimpleMix tested = new SimpleMix();
+ mockStatic(System.class);
+
+ when(System.currentTimeMillis()).thenReturn(2000L);
+
+ assertEquals(2, Whitebox.invokeMethod(tested, "getValue"));
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/spy/SpyTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/spy/SpyTest.java
new file mode 100644
index 0000000..b2b2ee2
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/spy/SpyTest.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.spy;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.spy.SpyObject;
+import samples.suppressmethod.SuppressMethod;
+import samples.suppressmethod.SuppressMethodParent;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.method;
+import static org.powermock.api.support.membermodification.MemberModifier.suppress;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({SpyObject.class, SuppressMethod.class, SuppressMethodParent.class})
+public class SpyTest {
+
+ private SpyObject partialMock = null;
+
+ @Before
+ public void setup() throws Exception {
+ partialMock = spy(new SpyObject());
+ }
+
+ @Test
+ public void testSpyingOnPrivateMethodWorks() throws Exception {
+ when(partialMock, "getMyString").thenReturn("ikk2");
+
+ assertThat(partialMock.getMyString(), equalTo("ikk2"));
+ assertThat(partialMock.getStringTwo(), equalTo("two"));
+ }
+
+ @Test
+ public void testSuppressMethodWhenObjectIsSpy() throws Exception {
+ suppress(method(SuppressMethod.class, "myMethod"));
+
+ SuppressMethod tested = spy(new SuppressMethod());
+ assertEquals(0, tested.myMethod());
+ }
+
+ @Test
+ public void testSuppressMethodInParentOnlyWhenObjectIsSpy() throws Exception {
+ suppress(method(SuppressMethodParent.class, "myMethod"));
+
+ SuppressMethod tested = spy(new SuppressMethod());
+ assertEquals(20, tested.myMethod());
+ }
+
+ @Test
+ public void testDoNothingForSpy() {
+ doNothing().when(partialMock).throwException();
+
+ partialMock.throwException();
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticandinstance/StaticAndInstanceDemoTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticandinstance/StaticAndInstanceDemoTest.java
new file mode 100644
index 0000000..77b9558
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticandinstance/StaticAndInstanceDemoTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.staticandinstance;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.staticandinstance.StaticAndInstanceDemo;
+
+import static org.junit.Assert.assertEquals;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(StaticAndInstanceDemo.class)
+public class StaticAndInstanceDemoTest {
+
+ @Test
+ public void partialMockingOfStaticAndInstanceMethod() throws Exception {
+ spy(StaticAndInstanceDemo.class);
+ StaticAndInstanceDemo tested = spy(new StaticAndInstanceDemo());
+
+ final String staticExpected = "a static message";
+ when(StaticAndInstanceDemo.getStaticMessage()).thenReturn(staticExpected);
+ final String privateExpected = "A private message ";
+ when(tested, "getPrivateMessage").thenReturn(privateExpected);
+
+ String actual = tested.getMessage();
+
+ verifyStatic(); StaticAndInstanceDemo.getStaticMessage();
+ verifyPrivate(tested).invoke("getPrivateMessage");
+ assertEquals(privateExpected + staticExpected, actual);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticNotPreparedTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticNotPreparedTest.java
new file mode 100644
index 0000000..e527e0a
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticNotPreparedTest.java
@@ -0,0 +1,58 @@
+package samples.powermockito.junit4.staticmocking;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.powermock.api.mockito.ClassNotPreparedException;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.StaticService;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+/**
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+public class MockStaticNotPreparedTest {
+
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+
+ @Test
+ public void testWhenNotPrepared() throws Exception {
+
+ assertOverwrittenException();
+
+ }
+
+ @PrepareForTest(StaticService.class)
+ @Test
+ public void testWhenPreparedButMockStaticIsNotCalled() throws Exception {
+
+ assertOverwrittenException();
+
+ }
+
+
+ @Test(expected = ClassNotPreparedException.class)
+ public void testWhenNotPreparedAndMockStaticIsCalled() throws Exception {
+
+ mockStatic(StaticService.class);
+
+ }
+
+ private void assertOverwrittenException() {
+ expectedException.expect(MissingMethodInvocationException.class);
+ expectedException.expectMessage(containsString("PrepareForTest"));
+
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ when(StaticService.say(argument)).thenReturn(expected);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticTest.java
new file mode 100644
index 0000000..12745fa
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/staticmocking/MockStaticTest.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.staticmocking;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.mockito.exceptions.verification.TooLittleActualInvocations;
+import org.mockito.exceptions.verification.junit.ArgumentsAreDifferent;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.singleton.SimpleStaticService;
+import samples.singleton.StaticService;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.spy;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+
+/**
+ * Test class to demonstrate static mocking with PowerMockito.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, SimpleStaticService.class })
+public class MockStaticTest {
+
+ @Test
+ public void testMockStaticNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticWithExpectations() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say(argument);
+ }
+
+ @Test
+ public void errorousVerificationOfStaticMethodsGivesANonMockitoStandardMessage() throws Exception {
+ final String expected = "Hello world";
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenReturn(expected);
+
+ assertEquals(expected, StaticService.say(argument));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ try {
+ StaticService.say(argument);
+ fail("Should throw assertion error");
+ } catch (MockitoAssertionError e) {
+ assertEquals("\nsamples.singleton.StaticService.say(\"hello\");\nWanted 2 times but was 1 time.", e.getMessage());
+ }
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testMockStaticThatThrowsException() throws Exception {
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ when(StaticService.say(argument)).thenThrow(new IllegalStateException());
+
+ StaticService.say(argument);
+ }
+
+ @Test(expected = ArgumentsAreDifferent.class)
+ // TODO Fix error message!!
+ public void testMockStaticVerificationFails() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic();
+ StaticService.say("Hello");
+ }
+
+ @Test
+ public void testMockStaticAtLeastOnce() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(atLeastOnce());
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticCorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(2));
+ StaticService.say("hello");
+ }
+
+ @Test(expected = TooLittleActualInvocations.class)
+ public void testMockStaticIncorrectTimes() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+ assertNull(StaticService.say("hello"));
+
+ // Verification is done in two steps using static methods.
+ verifyStatic(times(3));
+ StaticService.say("hello");
+ }
+
+ @Test
+ public void testMockStaticVoidWithNoExpectations() throws Exception {
+ mockStatic(StaticService.class);
+
+ StaticService.sayHello();
+
+ verifyStatic();
+ StaticService.sayHello();
+ }
+
+ @Test(expected = ArrayStoreException.class)
+ public void testMockStaticVoidWhenThrowingException() throws Exception {
+ mockStatic(StaticService.class);
+
+ // Expectations
+ doThrow(new ArrayStoreException("Mock error")).when(StaticService.class);
+ StaticService.sayHello();
+
+ // Test
+ StaticService.sayHello();
+ }
+
+ @Test
+ public void testSpyOnStaticMethods() throws Exception {
+ spy(StaticService.class);
+
+ String expectedMockValue = "expected";
+ when(StaticService.say("world")).thenReturn(expectedMockValue);
+
+ assertEquals(expectedMockValue, StaticService.say("world"));
+ assertEquals("Hello world2", StaticService.say("world2"));
+ }
+
+ @Test
+ public void mockStatic_uses_var_args_to_create_multiple_static_mocks() throws Exception {
+ mockStatic(StaticService.class, SimpleStaticService.class);
+
+ when(SimpleStaticService.say("Something")).thenReturn("other");
+
+ StaticService.sayHello();
+ final String said = SimpleStaticService.say("Something");
+
+ verifyStatic();
+ StaticService.sayHello();
+ verifyStatic();
+ SimpleStaticService.say("Something");
+
+ assertEquals(said, "other");
+ }
+
+ @Test
+ public void spyingUsingArgumentCaptor() throws Exception {
+ // Given
+ mockStatic(StaticService.class);
+ final ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
+
+ StaticService.say("something");
+
+ verifyStatic();
+ StaticService.say(captor.capture());
+
+ assertEquals("something", captor.getValue());
+ }
+
+ @Test
+ public void testMockStaticWithExpectations_withDo() throws Exception {
+ final String argument = "hello";
+
+ mockStatic(StaticService.class);
+
+ doNothing().when(StaticService.class,"sayHello",any(String.class));
+
+ StaticService.sayHello(argument);
+
+ assertThat(StaticService.messageStorage).isNull();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/stress/PowerMockStressTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/stress/PowerMockStressTest.java
new file mode 100644
index 0000000..691b1ad
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/stress/PowerMockStressTest.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.stress;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.stress.ClassWithStatic;
+import samples.stress.StressSample;
+
+import static org.mockito.Mockito.when;
+
+/**
+ * Test that asserts that <a href="http://code.google.com/p/powermock/issues/detail?id=308">issue 308</a> is resolved.
+ * The problem was that finalize methods could be called before an expected method because the GC kicked in too soon
+ * since now object held a reference to the mock.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({ClassWithStatic.class})
+public class PowerMockStressTest {
+
+ private StressSample underTest = new StressSample();
+
+ @Before
+ public void setUp(){
+ PowerMockito.mockStatic(ClassWithStatic.class);
+ for (int i = 0; i < 1000; i++) { // 100*8executions
+ createWhen();
+ }
+ }
+ public void createWhen(){
+ when(ClassWithStatic.a()).thenReturn("A");
+ when(ClassWithStatic.b()).thenReturn("B");
+ when(ClassWithStatic.c()).thenReturn("C");
+ when(ClassWithStatic.d()).thenReturn("D");
+ when(ClassWithStatic.e()).thenReturn("E");
+ when(ClassWithStatic.f()).thenReturn("F");
+ when(ClassWithStatic.g()).thenReturn("G");
+ when(ClassWithStatic.h()).thenReturn("H");
+ }
+
+ @Test
+ public void test1(){
+ underTest.a1();
+ }
+ @Test
+ public void test2(){
+ underTest.b1();
+ }
+ @Test
+ public void test3(){
+ underTest.c1();
+ }
+ @Test
+ public void test4(){
+ underTest.d1();
+ }
+ @Test
+ public void test5(){
+ underTest.e1();
+ }
+ @Test
+ public void test6(){
+ underTest.f1();
+ }
+ @Test
+ public void test7(){
+ underTest.g1();
+ }
+ @Test
+ public void test8(){
+ underTest.h1();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/ServiceLoaderTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/ServiceLoaderTest.java
new file mode 100644
index 0000000..0c8d08a
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/ServiceLoaderTest.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.system;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.ServiceLoader;
+
+import static org.powermock.api.mockito.PowerMockito.doThrow;
+import static org.powermock.api.mockito.PowerMockito.mock;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ServiceLoader.class)
+public class ServiceLoaderTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void supportsMockingServiceLoader() throws Exception {
+ final ServiceLoader mock = mock(ServiceLoader.class);
+
+ doThrow(new IllegalArgumentException("something")).when(mock).reload();
+
+ mock.reload();
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/SystemClassUserTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/SystemClassUserTest.java
new file mode 100644
index 0000000..67f4b62
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/system/SystemClassUserTest.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.system;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.system.SystemClassUser;
+
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+
+import static org.junit.Assert.*;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Matchers.anyLong;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+/**
+ * Demonstrates PowerMockito's ability to mock non-final and final system
+ * classes. To mock a system class you need to prepare the calling class for
+ * testing. I.e. let's say you're testing class A which interacts with
+ * URLEncoder then you would do:
+ *
+ * <pre>
+ *
+ * @PrepareForTest({A.class})
+ *
+ * </pre>
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest({ SystemClassUser.class })
+public class SystemClassUserTest {
+
+ @Test
+ public void assertThatMockingOfNonFinalSystemClassesWorks() throws Exception {
+ mockStatic(URLEncoder.class);
+
+ when(URLEncoder.encode("string", "enc")).thenReturn("something");
+
+ assertEquals("something", new SystemClassUser().performEncode());
+
+ }
+
+ @Test
+ public void assertThatMockingOfTheRuntimeSystemClassWorks() throws Exception {
+ mockStatic(Runtime.class);
+
+ Runtime runtimeMock = mock(Runtime.class);
+ Process processMock = mock(Process.class);
+
+ when(Runtime.getRuntime()).thenReturn(runtimeMock);
+ when(runtimeMock.exec("command")).thenReturn(processMock);
+
+ assertSame(processMock, new SystemClassUser().executeCommand());
+ }
+
+ @Test
+ public void assertThatMockingOfFinalSystemClassesWorks() throws Exception {
+ mockStatic(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ assertEquals("my property", new SystemClassUser().getSystemProperty());
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorks() throws Exception {
+ spy(System.class);
+
+ when(System.nanoTime()).thenReturn(2L);
+
+ new SystemClassUser().doMoreComplicatedStuff();
+
+ assertEquals("2", System.getProperty("nanoTime"));
+ }
+
+ @Test
+ public void assertThatMockingOfCollectionsWork() throws Exception {
+ List<?> list = new LinkedList<Object>();
+ mockStatic(Collections.class);
+
+ Collections.shuffle(list);
+
+ new SystemClassUser().shuffleCollection(list);
+
+ verifyStatic(times(2));
+ Collections.shuffle(list);
+ }
+
+ @Test
+ public void assertThatPartialMockingOfFinalSystemClassesWorksForNonVoidMethods() throws Exception {
+ spy(System.class);
+
+ when(System.getProperty("property")).thenReturn("my property");
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.copyProperty("to", "property");
+ }
+
+ @Test
+ public void assertThatMockingStringWorks() throws Exception {
+ mockStatic(String.class);
+ final String string = "string";
+ final String args = "args";
+ final String returnValue = "returnValue";
+
+ when(String.format(string, args)).thenReturn(returnValue);
+
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ assertEquals(systemClassUser.format(string, args), returnValue);
+ }
+
+ @Test
+ public void mockingStaticVoidMethodWorks() throws Exception {
+ mockStatic(Thread.class);
+ doNothing().when(Thread.class);
+ Thread.sleep(anyLong());
+
+ long startTime = System.currentTimeMillis();
+ final SystemClassUser systemClassUser = new SystemClassUser();
+ systemClassUser.threadSleep();
+ long endTime = System.currentTimeMillis();
+ assertTrue(endTime - startTime < 5000);
+ }
+
+ @Test
+ public void mockingURLWorks() throws Exception {
+ URL url = mock(URL.class);
+ URLConnection urlConnectionMock = mock(URLConnection.class);
+
+ when(url.openConnection()).thenReturn(urlConnectionMock);
+
+ URLConnection openConnection = url.openConnection();
+
+ assertSame(openConnection, urlConnectionMock);
+ }
+
+ @Test
+ public void mockingUUIDWorks() throws Exception {
+ // given
+ final UUID mock = mock(UUID.class);
+ mockStatic(UUID.class);
+ given(UUID.randomUUID()).willReturn(mock);
+
+ // when
+ String actual = new SystemClassUser().generatePerishableToken();
+
+ // then
+ assertEquals("00000000000000000000000000000000", actual);
+ }
+
+ @Test
+ public void mockingNewURLWorks() throws Exception {
+ // Given
+ final URL url = mock(URL.class);
+ whenNew(URL.class).withArguments("some_url").thenReturn(url);
+
+ // When
+ final URL actual = new SystemClassUser().newURL("some_url");
+
+ // Then
+ assertSame(url, actual);
+ }
+
+ @Test
+ public void mockingStringBuilder() throws Exception {
+ // Given
+ final StringBuilder mock = mock(StringBuilder.class);
+ whenNew(StringBuilder.class).withNoArguments().thenReturn(mock);
+ when(mock.toString()).thenReturn("My toString");
+
+ // When
+ final StringBuilder actualStringBuilder = new SystemClassUser().newStringBuilder();
+ final String actualToString = actualStringBuilder.toString();
+
+
+ // Then
+ assertSame(mock, actualStringBuilder);
+ assertEquals("My toString", actualToString);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void triggerMockedCallFromInterfaceTypeInsteadOfConcreteType() throws Exception
+ {
+ StringBuilder builder = mock(StringBuilder.class);
+ when(builder.length()).then(new Answer<StringBuilder>(){
+ public StringBuilder answer(InvocationOnMock invocation) throws Throwable{
+ throw new IllegalStateException("Can't really happen");
+ }
+ });
+ new SystemClassUser().lengthOf(builder);
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/tostring/ToStringTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/tostring/ToStringTest.java
new file mode 100644
index 0000000..9b5b9bb
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/tostring/ToStringTest.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.tostring;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.mockito.PowerMockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import javax.crypto.Cipher;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * Test that demonstrates that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=239">issue 239</a>
+ * is resolved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(ToStringTest.class)
+public class ToStringTest {
+ private Cipher cipher;
+
+ @Test
+ public void toStringInvocationWorksInMockito() throws Exception {
+ cipher = PowerMockito.mock(Cipher.class);
+
+ assertNotNull(cipher.toString());
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/verifynomoreinteractions/VerifyNoMoreInteractionsTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/verifynomoreinteractions/VerifyNoMoreInteractionsTest.java
new file mode 100644
index 0000000..b5c120f
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/verifynomoreinteractions/VerifyNoMoreInteractionsTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.verifynomoreinteractions;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.exceptions.base.MockitoAssertionError;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+import samples.newmocking.MyClass;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.times;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate static mocking with PowerMockito.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticService.class, StaticHelper.class, ExpectNewDemo.class })
+public class VerifyNoMoreInteractionsTest {
+
+ @Test
+ public void verifyNoMoreInteractionsForStaticMethodsReturnsSilentlyWhenNoMoreInteractionsTookPlace() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ verifyStatic();
+ StaticService.say("hello");
+ verifyNoMoreInteractions(StaticService.class);
+ }
+
+ @Test
+ public void verifyNoMoreInteractionsOnMethodThrowsAssertionErrorWhenMoreInteractionsTookPlace() throws Exception {
+ mockStatic(StaticService.class);
+ assertNull(StaticService.say("hello"));
+
+ try {
+ verifyNoMoreInteractions(StaticService.class);
+ fail("Should throw exception!");
+ } catch (MockitoAssertionError e) {
+ assertTrue(e
+ .getMessage()
+ .startsWith(
+ "\nNo interactions wanted here:\n-> at samples.powermockito.junit4.verifynomoreinteractions.VerifyNoMoreInteractionsTest.verifyNoMoreInteractionsOnMethodThrowsAssertionErrorWhenMoreInteractionsTookPlace(VerifyNoMoreInteractionsTest.java"));
+ }
+ }
+
+ @Test
+ public void verifyNoMoreInteractionsOnNewInstancesThrowsAssertionErrorWhenMoreInteractionsTookPlace() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNoMoreInteractions(MyClass.class);
+ fail("Should throw exception!");
+ } catch (MockitoAssertionError e) {
+ assertTrue(e
+ .getMessage()
+ .startsWith(
+ "\nNo interactions wanted here:\n-> at samples.powermockito.junit4.verifynomoreinteractions.VerifyNoMoreInteractionsTest.verifyNoMoreInteractionsOnNewInstancesThrowsAssertionErrorWhenMoreInteractionsTookPlace(VerifyNoMoreInteractionsTest.java:"));
+ }
+ }
+
+ @Test
+ public void verifyNoMoreInteractionsOnNewInstancesWorks() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ verifyNoMoreInteractions(MyClass.class);
+ }
+
+ @Test
+ public void verifyNoMoreInteractionsOnNewInstancesWorksWhenUsingConstructorToExpect() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(constructor(MyClass.class)).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ verifyNoMoreInteractions(MyClass.class);
+ }
+
+ @Test
+ public void verifyNoMoreInteractionsDelegatesToPlainMockitoWhenMockIsNotAPowerMockitoMock() throws Exception {
+ MyClass myClassMock = Mockito.mock(MyClass.class);
+ myClassMock.getMessage();
+
+ try {
+ verifyNoMoreInteractions(myClassMock);
+ fail("Should throw exception!");
+ } catch (AssertionError e) {
+ /*
+ * This string would have been deleted by PowerMockito but should
+ * exists if delegation took place.
+ */
+ final String expectedTextThatProvesDelegation = "But found this interaction";
+ assertTrue(e.getMessage().contains(expectedTextThatProvesDelegation));
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/DoesntSupportCreatingMocksInFieldsWhenNewDefect.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/DoesntSupportCreatingMocksInFieldsWhenNewDefect.java
new file mode 100644
index 0000000..b9abe8e
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/DoesntSupportCreatingMocksInFieldsWhenNewDefect.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.powermockito.junit4.whennew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.newmocking.NewDemo;
+import samples.newmocking.SomeDependency;
+
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.whenNew;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { NewDemo.class })
+/**
+ * Issue <a href="298">http://code.google.com/p/powermock/issues/detail?id=298</a>
+ */
+public class DoesntSupportCreatingMocksInFieldsWhenNewDefect {
+
+ final SomeDependency somethingUsedByMethodUnderTest=mock(SomeDependency.class); // for some reason the mocking only works if loadingPool is a local variable not a field (like all the other mocks)
+
+ @Test
+ public void methodUnderTestShouldWorkWithClassLevelMock() throws Exception {
+
+ whenNew(SomeDependency.class).withNoArguments().thenReturn(somethingUsedByMethodUnderTest);
+
+ NewDemo objectUnderTest = new NewDemo();
+
+ objectUnderTest.methodUnderTest();
+
+ }
+
+
+
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/NewFileExampleTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/NewFileExampleTest.java
new file mode 100644
index 0000000..9ce7f28
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/NewFileExampleTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.whennew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.NewFileExample;
+
+import java.io.File;
+
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(NewFileExample.class)
+public class NewFileExampleTest {
+ @Test
+ public void assertThatMockingFileWorks() throws Exception {
+ final String directoryPath = "mocked path";
+
+ File directoryMock = mock(File.class);
+
+ whenNew(File.class).withArguments(directoryPath).thenReturn(directoryMock);
+ when(directoryMock.exists()).thenReturn(false);
+ when(directoryMock.mkdirs()).thenReturn(true);
+
+ assertTrue(new NewFileExample().createDirectoryStructure(directoryPath));
+
+ verifyNew(File.class).withArguments(directoryPath);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewMultipleTimesTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewMultipleTimesTest.java
new file mode 100644
index 0000000..1ecb0de
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewMultipleTimesTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.whennew;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.NewFileExample;
+
+import java.io.File;
+
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.powermock.api.mockito.PowerMockito.*;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest(NewFileExample.class)
+public class VerifyNewMultipleTimesTest {
+ private final static String DIRECTORY_PATH = "mocked path";
+ @Mock
+ private File directoryMock;
+
+ @Before
+ public void setUp() throws Exception {
+ MockitoAnnotations.initMocks(this);
+
+ whenNew(File.class).withArguments(DIRECTORY_PATH).thenReturn(directoryMock);
+
+ when(directoryMock.exists()).thenReturn(false);
+ when(directoryMock.mkdirs()).thenReturn(true);
+ }
+
+ @Test(expected=AssertionError.class)
+ public void verifyNewTooManyTimesCausesAssertionError() throws Exception {
+ assertTrue(new NewFileExample().createDirectoryStructure((DIRECTORY_PATH)));
+
+ verify(directoryMock).mkdirs();
+
+ // Correct usage
+ verifyNew(File.class, times(1)).withArguments(DIRECTORY_PATH);
+
+ // Should throw
+ verifyNew(File.class, times(100000)).withArguments(DIRECTORY_PATH);
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewWithoutWhenNewTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewWithoutWhenNewTest.java
new file mode 100644
index 0000000..33f6f27
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/VerifyNewWithoutWhenNewTest.java
@@ -0,0 +1,52 @@
+package samples.powermockito.junit4.whennew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.expectnew.ExpectNewDemo;
+import samples.newmocking.MyClass;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+import static org.powermock.api.mockito.PowerMockito.verifyNew;
+
+ at PrepareForTest(ExpectNewDemo.class)
+ at RunWith(PowerMockRunner.class)
+public class VerifyNewWithoutWhenNewTest {
+
+ @Test
+ // TODO This should actually work in the future when issue 148 is resolved.
+ public void verifyingNewWithoutExpectationWhenNoArgumentsThrowsISE() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ assertEquals("Hello world", tested.getMessage());
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ assertEquals("No instantiation of class samples.newmocking.MyClass was recorded "
+ + "during the test. Note that only expected object creations "
+ + "(e.g. those using whenNew(..)) can be verified.", e.getMessage());
+ }
+
+ }
+
+ @Test
+ // TODO This should actually work in the future when issue 148 is resolved.
+ public void verifyingNewWithoutExpectationButWithArgumentsThrowsISE() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ assertEquals("Hello world", tested.getMessage());
+
+ try {
+ verifyNew(MyClass.class, Mockito.atLeastOnce()).withNoArguments();
+ fail("IllegalStateException expected");
+ } catch (IllegalStateException e) {
+ assertEquals("No instantiation of class samples.newmocking.MyClass was recorded "
+ + "during the test. Note that only expected object creations "
+ + "(e.g. those using whenNew(..)) can be verified.", e.getMessage());
+ }
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/WhenNewTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/WhenNewTest.java
new file mode 100644
index 0000000..073be90
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/whennew/WhenNewTest.java
@@ -0,0 +1,635 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.whennew;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.stubbing.OngoingStubbing;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import org.powermock.reflect.Whitebox;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import samples.Service;
+import samples.expectnew.ExpectNewDemo;
+import samples.expectnew.ExpectNewServiceUser;
+import samples.expectnew.ExpectNewWithMultipleCtorDemo;
+import samples.expectnew.VarArgsConstructorDemo;
+import samples.newmocking.MyClass;
+
+import java.io.ByteArrayInputStream;
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.doNothing;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.*;
+import static org.powermock.api.mockito.PowerMockito.when;
+import static org.powermock.api.support.membermodification.MemberMatcher.constructor;
+
+/**
+ * Test class to demonstrate new instance mocking using whenConstructionOf(..).
+ *
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { MyClass.class, ExpectNewDemo.class, DataInputStream.class })
+public class WhenNewTest {
+
+ @Test
+ public void testNewWithCheckedException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing checked exception";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new IOException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionAndWrapInRunTimeWhenInvoction();
+ fail("Should throw a checked Exception!");
+ } catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testGetMessage() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage()).thenReturn("Hello altered World");
+
+ String actual = tested.getMessage();
+
+ verify(myClassMock).getMessage();
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testGetMessageWithArgument() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ String expected = "Hello altered World";
+ when(myClassMock.getMessage("test")).thenReturn("Hello altered World");
+
+ String actual = tested.getMessageWithArgument();
+
+ verify(myClassMock).getMessage("test");
+ verifyNew(MyClass.class).withNoArguments();
+ assertEquals("Expected and actual did not match", expected, actual);
+ }
+
+ @Test
+ public void testInvokeVoidMethod() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ doNothing().when(myClassMock).voidMethod();
+
+ tested.invokeVoidMethod();
+
+ verify(myClassMock).voidMethod();
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testNewWithRuntimeException() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ final String expectedFailMessage = "testing";
+ whenNew(MyClass.class).withNoArguments().thenThrow(new RuntimeException(expectedFailMessage));
+
+ try {
+ tested.throwExceptionWhenInvoction();
+ fail("Should throw RuntimeException!");
+ } catch (RuntimeException e) {
+ assertEquals(expectedFailMessage, e.getMessage());
+ }
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void testSimpleMultipleNew() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock);
+
+ tested.simpleMultipleNew();
+
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNew_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+ try {
+ verifyNew(MyClass.class, times(1)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 1 time but was 3 times.", e.getMessage());
+ }
+ }
+
+ /**
+ * Verifies that the issue
+ * http://code.google.com/p/powermock/issues/detail?id=10 is solved.
+ */
+ @Test
+ public void testSimpleMultipleNewPrivate_tooFewTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ try {
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+ fail("Should throw AssertionError.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 2 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_ok() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+
+ verifyNew(MyClass.class, times(3)).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleSingleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleSingleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ @Test
+ public void testSimpleMultipleNew_withAtLeastOnce() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.simpleMultipleNew();
+
+ verifyNew(MyClass.class, atLeastOnce()).withNoArguments();
+ }
+
+ //
+ @Test
+ public void testAlternativeFlow() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ whenNew(DataInputStream.class).withArguments(null).thenThrow(new RuntimeException("error"));
+
+ InputStream stream = tested.alternativePath();
+
+ verifyNew(DataInputStream.class).withArguments(null);
+
+ assertNotNull("The returned inputstream should not be null.", stream);
+ assertTrue("The returned inputstream should be an instance of ByteArrayInputStream.", stream instanceof ByteArrayInputStream);
+ }
+
+ @Test
+ public void testSimpleMultipleNewPrivate_tooManyTimesExpected() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ Whitebox.invokeMethod(tested, "simpleMultipleNewPrivate");
+ try {
+ verifyNew(MyClass.class, times(4)).withNoArguments();
+ fail("Should throw an exception!.");
+ } catch (AssertionError e) {
+ assertEquals("samples.newmocking.MyClass();\nWanted 4 times but was 3 times.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withParameterTypes(Service.class, int.class).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithConstructorUsingParameterTypesAndArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class, Service.class, int.class)).withArguments(serviceMock, numberOfTimes).thenReturn(
+ expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewUsingConstructorWithArguments() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(constructor(ExpectNewServiceUser.class)).withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ }
+
+ @Test
+ public void testNewWithVarArgs() throws Exception {
+ final String firstString = "hello";
+ final String secondString = "world";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllMessages()).thenReturn(new String[] { firstString, secondString });
+
+ String[] varArgs = tested.newVarArgs(firstString, secondString);
+ assertEquals(2, varArgs.length);
+ assertEquals(firstString, varArgs[0]);
+ assertEquals(secondString, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(firstString, secondString);
+ }
+
+ @Test
+ public void testNewWhenTheExpectedConstructorIsNotFound() throws Exception {
+ final Object object = new Object();
+ try {
+ whenNew(VarArgsConstructorDemo.class).withArguments(object);
+ fail("Should throw ConstructorNotFoundException!");
+ } catch (ConstructorNotFoundException e) {
+ assertEquals("No constructor found in class '" + VarArgsConstructorDemo.class.getName() + "' with parameter types: [ "
+ + object.getClass().getName() + " ].", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testNewWithVarArgsConstructorWhenOneArgumentIsOfASubType() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ Service serviceMock = mock(Service.class);
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final Service serviceSubTypeInstance = new Service() {
+
+ @Override
+ public String getServiceMessage() {
+ return "message";
+ }
+ };
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getAllServices()).thenReturn(new Service[] { serviceMock });
+
+ Service[] varArgs = tested.newVarArgs(serviceSubTypeInstance, serviceMock);
+ assertEquals(1, varArgs.length);
+ assertSame(serviceMock, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(serviceSubTypeInstance, serviceMock);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgs() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsAndMatchers() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgsWithMatchers();
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullAndSubseqentArgumentsAreNotNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 17 };
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNotNullButSubseqentArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = new byte[] { 42 };
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayOne });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayOne, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenFirstArgumentIsNullSecondArgumentIsNotNullAndThirdArgumentIsNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = new byte[] { 42 };
+ final byte[] byteArrayThree = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo, byteArrayThree);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo, byteArrayThree);
+ }
+
+ @Test
+ public void testNewWithArrayVarArgsWhenAllArgumentsAreNull() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ final byte[] byteArrayOne = null;
+ final byte[] byteArrayTwo = null;
+ whenNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getByteArrays()).thenReturn(new byte[][] { byteArrayTwo });
+
+ byte[][] varArgs = tested.newVarArgs(byteArrayOne, byteArrayTwo);
+ assertEquals(1, varArgs.length);
+ assertSame(byteArrayTwo, varArgs[0]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(byteArrayOne, byteArrayTwo);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNewWithWrongArgument() throws Exception {
+ final int numberOfTimes = 2;
+ final String expected = "used";
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ ExpectNewServiceUser expectNewServiceImplMock = mock(ExpectNewServiceUser.class);
+ Service serviceMock = mock(Service.class);
+
+ whenNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes).thenReturn(expectNewServiceImplMock);
+ when(expectNewServiceImplMock.useService()).thenReturn(expected);
+
+ assertEquals(expected, tested.newWithWrongArguments(serviceMock, numberOfTimes));
+
+ verifyNew(ExpectNewServiceUser.class).withArguments(serviceMock, numberOfTimes);
+ /*
+ * Should throw NPE because the default behavior of Mockito when a
+ * something isn't expected is to return a default value. In this case
+ * whenConstructionOf
+ * (ExpectNewServiceUser.class).withArguments(serviceMock,
+ * numberOfTimes) is the wrong expectation and thus null is returned
+ * from the substitute mock which is the correct behavior.
+ */
+ fail("Should throw NPE!");
+ }
+
+ @Test
+ public void testExpectNewButNoNewCallWasMade() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock1 = mock(MyClass.class);
+
+ whenNew(MyClass.class).withNoArguments().thenReturn(myClassMock1);
+
+ tested.makeDate();
+
+ try {
+ verifyNew(MyClass.class).withNoArguments();
+ fail("Should throw AssertionError!");
+ } catch (AssertionError e) {
+ assertEquals("Wanted but not invoked samples.newmocking.MyClass();\nActually, there were zero interactions with this mock.", e
+ .getMessage());
+ }
+ }
+
+ @Test
+ public void whenNewSupportsVarArgsAsSecondParameter() throws Exception {
+ final int one = 1;
+ final int two = 2;
+ final float myFloat = 3.0f;
+
+ ExpectNewDemo tested = new ExpectNewDemo();
+ VarArgsConstructorDemo varArgsConstructorDemoMock = mock(VarArgsConstructorDemo.class);
+
+ whenNew(VarArgsConstructorDemo.class).withArguments(myFloat, one, two).thenReturn(varArgsConstructorDemoMock);
+ when(varArgsConstructorDemoMock.getInts()).thenReturn(new int[] { one, two});
+
+ int[] varArgs = tested.newVarArgs(myFloat, one, two);
+ assertEquals(2, varArgs.length);
+ assertEquals(one, varArgs[0]);
+ assertEquals(two, varArgs[1]);
+
+ verifyNew(VarArgsConstructorDemo.class).withArguments(myFloat, one, two);
+ }
+
+ @Test
+ public void whenNewAnyArgumentsWorksInClassesWithSingleCtor() throws Exception {
+ ExpectNewDemo tested = new ExpectNewDemo();
+
+ MyClass myClassMock = mock(MyClass.class);
+
+ whenNew(MyClass.class).withAnyArguments().thenReturn(myClassMock);
+
+ when(myClassMock.getMessage()).thenReturn("Hello");
+
+ final String actual = tested.multipleNew();
+
+ verify(myClassMock, times(2)).getMessage();
+ verifyNew(MyClass.class, times(2)).withNoArguments();
+
+ assertEquals("HelloHello", actual);
+ }
+
+ @Test
+ public void whenNewAnyArgumentsWorksInClassesWithMultipleCtors() throws Exception {
+ ExpectNewWithMultipleCtorDemo mock1 = mock(ExpectNewWithMultipleCtorDemo.class);
+ Service mock2 = mock(Service.class);
+
+ whenNew(ExpectNewWithMultipleCtorDemo.class).withAnyArguments().thenReturn(mock1);
+ when(mock1.useService()).thenReturn("message");
+
+ // When
+ final String message1 = new ExpectNewWithMultipleCtorDemo(mock2).useService();
+ final String message2 = new ExpectNewWithMultipleCtorDemo(mock2, 5).useService();
+
+
+ assertEquals(message1, "message");
+ assertEquals(message2, "message");
+ }
+}
diff --git a/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/withsettings/WithSettingsTest.java b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/withsettings/WithSettingsTest.java
new file mode 100644
index 0000000..36bc83a
--- /dev/null
+++ b/modules/module-test/mockito/junit4/src/test/java/samples/powermockito/junit4/withsettings/WithSettingsTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.withsettings;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+import samples.finalmocking.FinalDemo;
+import samples.finalmocking.HoldingFinalDemo;
+import samples.finalmocking.StaticHoldingFinalDemo;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.RETURNS_MOCKS;
+import static org.mockito.Mockito.withSettings;
+import static org.powermock.api.mockito.PowerMockito.mock;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { StaticHoldingFinalDemo.class, HoldingFinalDemo.class, FinalDemo.class })
+public class WithSettingsTest {
+
+ @Test
+ public void powermockitoSupportsAnswersForInstanceMethods() {
+ HoldingFinalDemo tested = mock(HoldingFinalDemo.class, RETURNS_MOCKS);
+ assertNotNull(tested.getFinalDemo());
+ }
+
+ @Test
+ public void powermockitoSupportsWithSettingsForInstanceMethods() {
+ HoldingFinalDemo tested = mock(HoldingFinalDemo.class, withSettings().defaultAnswer(RETURNS_MOCKS));
+ assertNotNull(tested.getFinalDemo());
+ }
+
+ @Test
+ public void powermockitoSupportsAnswersForStaticMethods() {
+ mockStatic(StaticHoldingFinalDemo.class, RETURNS_MOCKS);
+ assertNotNull(StaticHoldingFinalDemo.getFinalDemo());
+ }
+
+ @Test
+ public void powermockitoSupportsWithSettingsForStaticMethods() {
+ mockStatic(StaticHoldingFinalDemo.class, withSettings().defaultAnswer(RETURNS_MOCKS));
+ assertNotNull(StaticHoldingFinalDemo.getFinalDemo());
+ }
+}
diff --git a/modules/module-test/mockito/junit49/pom.xml b/modules/module-test/mockito/junit49/pom.xml
new file mode 100644
index 0000000..2c54a73
--- /dev/null
+++ b/modules/module-test/mockito/junit49/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-mockito-junit49-test</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with JUnit 4.9.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/mockito/junit49/src/test/java/samples/powermockito/junit4/rules/JUnit49RuleTest.java b/modules/module-test/mockito/junit49/src/test/java/samples/powermockito/junit4/rules/JUnit49RuleTest.java
new file mode 100644
index 0000000..74b63b7
--- /dev/null
+++ b/modules/module-test/mockito/junit49/src/test/java/samples/powermockito/junit4/rules/JUnit49RuleTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.junit4.rules;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.MethodRule;
+import org.junit.rules.TestName;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runner.RunWith;
+import org.junit.runners.model.FrameworkMethod;
+import org.junit.runners.model.Statement;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * JUnit 4.9 changed the implementation/execution of Rules.
+ * Demonstrates that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=344">issue 344</a>
+ * is resolved.
+ */
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { JUnit49RuleTest.class })
+public class JUnit49RuleTest {
+
+ private static Object BEFORE = new Object();
+
+ private List<Object> objects = new LinkedList<Object>();
+
+ @Rule
+ public MyRule rule = new MyRule();
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Test
+ public void assertThatJUnit47RulesWorks() throws Exception {
+ assertEquals(1, objects.size());
+ assertSame(BEFORE, objects.get(0));
+ assertEquals("assertThatJUnit47RulesWorks", testName.getMethodName());
+ }
+
+ private class MyRule implements TestRule {
+
+ @Override
+ public Statement apply(final Statement statement, Description description) {
+ return new Statement() {
+ @Override
+ public void evaluate() throws Throwable {
+ objects.add(BEFORE);
+ statement.evaluate();
+ }
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/modules/module-test/mockito/pom.xml b/modules/module-test/mockito/pom.xml
new file mode 100644
index 0000000..8f31316
--- /dev/null
+++ b/modules/module-test/mockito/pom.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <name>${project.artifactId}</name>
+ <packaging>pom</packaging>
+
+ <description>
+ Tests for Mockito module.
+ </description>
+
+ <profiles>
+ <profile>
+ <id>mockito</id>
+ <activation>
+ <activeByDefault>true</activeByDefault>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito-common</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ <profile>
+ <id>mockito2</id>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito-common</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito2.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ </profile>
+ </profiles>
+
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock.tests</groupId>
+ <artifactId>powermock-tests-utils</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <modules>
+ <module>junit4</module>
+ <module>junit49</module>
+ <module>junit4-rule-objenesis</module>
+ <module>junit4-rule-xstream</module>
+ <module>junit4-agent</module>
+ <module>junit4-delegate</module>
+ <module>testng</module>
+ <module>junit4-java8</module>
+ <module>junit4-java8-agent</module>
+ <module>junit4-java8-rule-xstream</module>
+ </modules>
+</project>
diff --git a/modules/module-test/mockito/testng/pom.xml b/modules/module-test/mockito/testng/pom.xml
new file mode 100644
index 0000000..c2ddcd0
--- /dev/null
+++ b/modules/module-test/mockito/testng/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-modules-test-mockito</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-module-test-mockito-testng</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for Mockito module with TestNG.
+ </description>
+
+ <profiles>
+ <profile>
+ <id>mockito</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ <systemProperties>
+ <property>
+ <name>mockitoVersion</name>
+ <value>${mockito1.version}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>mockito2</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ <systemProperties>
+ <property>
+ <name>mockitoVersion</name>
+ <value>${mockito2.version}</value>
+ </property>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticNotPreparedTest.java b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticNotPreparedTest.java
new file mode 100644
index 0000000..70a75a5
--- /dev/null
+++ b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticNotPreparedTest.java
@@ -0,0 +1,31 @@
+package samples.powermockito.testng.staticmocking;
+
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.powermock.api.mockito.ClassNotPreparedException;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+import samples.singleton.StaticService;
+
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+
+public class MockStaticNotPreparedTest extends PowerMockTestCase {
+
+
+ @Test(expectedExceptions = ClassNotPreparedException.class)
+ public void testMockStatic() throws Exception {
+
+ mockStatic(StaticService.class);
+
+ }
+
+
+ @Test(expectedExceptions = MissingMethodInvocationException.class, expectedExceptionsMessageRegExp =
+ "(?s).*PrepareForTest(?s).*")
+ public void testWhenNotPrepared() throws Exception {
+
+ when(StaticService.say("Hello")).thenReturn("Hello World!");
+
+ }
+}
diff --git a/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticPreparedWithoutMockStaticTest.java b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticPreparedWithoutMockStaticTest.java
new file mode 100644
index 0000000..d6a6e4f
--- /dev/null
+++ b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/MockStaticPreparedWithoutMockStaticTest.java
@@ -0,0 +1,24 @@
+package samples.powermockito.testng.staticmocking;
+
+import org.mockito.exceptions.misusing.MissingMethodInvocationException;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+import samples.singleton.StaticService;
+
+import static org.powermock.api.mockito.PowerMockito.when;
+
+
+ at PrepareForTest(StaticService.class)
+public class MockStaticPreparedWithoutMockStaticTest extends PowerMockTestCase {
+
+
+ @Test(expectedExceptions = MissingMethodInvocationException.class, expectedExceptionsMessageRegExp =
+ "(?s).*PrepareForTest(?s).*", enabled
+ = false)
+ public void testWhenNotPrepared() throws Exception {
+
+ when(StaticService.say("Hello")).thenReturn("Hello World!");
+
+ }
+}
diff --git a/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito1MockStaticTest.java b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito1MockStaticTest.java
new file mode 100644
index 0000000..1a3279c
--- /dev/null
+++ b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito1MockStaticTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.testng.staticmocking;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockObjectFactory;
+import org.testng.Assert;
+import org.testng.IObjectFactory;
+import org.testng.annotations.ObjectFactory;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ */
+ at PrepareForTest({StaticService.class, StaticHelper.class})
+public class Mockito1MockStaticTest {
+
+ @ObjectFactory
+ public IObjectFactory getObjectFactory() {
+ return new PowerMockObjectFactory();
+ }
+
+ @Test
+ public void testMockStatic() throws Exception {
+
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ when(StaticService.say("hello")).thenReturn("Hello altered World");
+
+ String actual = StaticService.say("hello");
+
+ verifyStatic();
+ StaticService.say("hello");
+
+ Assert.assertEquals(expected, actual);
+ }
+
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ when(StaticService.sayFinal("hello")).thenReturn("Hello altered World");
+
+ String actual = StaticService.sayFinal("hello");
+
+ verifyStatic();
+ StaticService.sayFinal("hello");
+
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito2MockStaticTest.java b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito2MockStaticTest.java
new file mode 100644
index 0000000..a2666e9
--- /dev/null
+++ b/modules/module-test/mockito/testng/src/test/java/samples/powermockito/testng/staticmocking/Mockito2MockStaticTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.powermockito.testng.staticmocking;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockObjectFactory;
+import org.testng.Assert;
+import org.testng.IObjectFactory;
+import org.testng.annotations.ObjectFactory;
+import org.testng.annotations.Test;
+import samples.singleton.StaticHelper;
+import samples.singleton.StaticService;
+
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static org.powermock.api.mockito.PowerMockito.verifyStatic;
+import static org.powermock.api.mockito.PowerMockito.when;
+
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ */
+ at PrepareForTest({StaticService.class, StaticHelper.class})
+public class Mockito2MockStaticTest {
+
+ @ObjectFactory
+ public IObjectFactory getObjectFactory() {
+ return new PowerMockObjectFactory();
+ }
+
+
+ @Test
+ public void testMockStatic() throws Exception {
+
+ System.out.println("Skip test while Mockito doesn't deliver fix");
+
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ when(StaticService.say("hello")).thenReturn("Hello altered World");
+
+ String actual = StaticService.say("hello");
+
+ verifyStatic();
+ StaticService.say("hello");
+
+ Assert.assertEquals(expected, actual);
+ }
+
+
+ @Test
+ public void testMockStaticFinal() throws Exception {
+
+ System.out.println("Skip test while Mockito doesn't deliver fix");
+
+ mockStatic(StaticService.class);
+ String expected = "Hello altered World";
+ when(StaticService.sayFinal("hello")).thenReturn("Hello altered World");
+
+ String actual = StaticService.sayFinal("hello");
+
+ verifyStatic();
+ StaticService.sayFinal("hello");
+
+ Assert.assertEquals(expected, actual);
+ }
+}
diff --git a/modules/module-test/mockito/testng/suite.xml b/modules/module-test/mockito/testng/suite.xml
new file mode 100644
index 0000000..617c29b
--- /dev/null
+++ b/modules/module-test/mockito/testng/suite.xml
@@ -0,0 +1,39 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<suite name="PowerMockito TestNG" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
+ <test name="General">
+ <classes>
+ <class name="samples.powermockito.testng.staticmocking.MockStaticNotPreparedTest"/>
+ <class name="samples.powermockito.testng.staticmocking.MockStaticPreparedWithoutMockStaticTest"/>
+ </classes>
+ </test>
+ <test name="Mockito1">
+ <method-selectors>
+ <method-selector>
+ <script language="beanshell">
+ <![CDATA[
+ String str = System.getProperty("mockitoVersion");
+ str.startsWith("1");
+ ]]>
+ </script>
+ </method-selector>
+ </method-selectors>
+ <classes>
+ <class name="samples.powermockito.testng.staticmocking.Mockito1MockStaticTest"/>
+ </classes>
+ </test>
+ <test name="Mockito2">
+ <method-selectors>
+ <method-selector>
+ <script language="beanshell">
+ <![CDATA[
+ String str = System.getProperty("mockitoVersion");
+ str.startsWith("2")&&str.contains(".55");
+ ]]>
+ </script>
+ </method-selector>
+ </method-selectors>
+ <classes>
+ <class name="samples.powermockito.testng.staticmocking.Mockito2MockStaticTest"/>
+ </classes>
+ </test>
+</suite>
\ No newline at end of file
diff --git a/modules/module-test/pom.xml b/modules/module-test/pom.xml
new file mode 100644
index 0000000..a6d7600
--- /dev/null
+++ b/modules/module-test/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-modules-test</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests for mocking framework modules.
+ </description>
+
+ <modules>
+ <module>easymock</module>
+ <module>mockito</module>
+ <module>testng</module>
+ <module>junit4</module>
+ </modules>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/modules/module-test/testng/pom.xml b/modules/module-test/testng/pom.xml
new file mode 100644
index 0000000..f6a789e
--- /dev/null
+++ b/modules/module-test/testng/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>powermock-modules-test</artifactId>
+ <groupId>org.powermock</groupId>
+ <version>1.6.5</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>powermock-modules-test-testng</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Tests TestNG.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <suiteXmlFiles>
+ <suiteXmlFile>suite.xml</suiteXmlFile>
+ </suiteXmlFiles>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/modules/module-test/testng/src/test/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java b/modules/module-test/testng/src/test/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
new file mode 100644
index 0000000..dff1f80
--- /dev/null
+++ b/modules/module-test/testng/src/test/java/org/powermock/api/extension/proxyframework/ProxyFrameworkImpl.java
@@ -0,0 +1,18 @@
+package org.powermock.api.extension.proxyframework;
+
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ *
+ */
+public class ProxyFrameworkImpl implements ProxyFramework {
+ @Override
+ public Class<?> getUnproxiedType(Class<?> type) {
+ return type;
+ }
+
+ @Override
+ public boolean isProxy(Class<?> type) {
+ return false;
+ }
+}
diff --git a/modules/module-test/testng/src/test/java/samples/testng/SimpleBaseTest.java b/modules/module-test/testng/src/test/java/samples/testng/SimpleBaseTest.java
new file mode 100644
index 0000000..a814357
--- /dev/null
+++ b/modules/module-test/testng/src/test/java/samples/testng/SimpleBaseTest.java
@@ -0,0 +1,120 @@
+package samples.testng;
+
+import org.testng.Assert;
+import org.testng.ITestResult;
+import org.testng.TestListenerAdapter;
+import org.testng.TestNG;
+import org.testng.collections.Lists;
+import org.testng.xml.XmlClass;
+import org.testng.xml.XmlInclude;
+import org.testng.xml.XmlSuite;
+import org.testng.xml.XmlTest;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+public class SimpleBaseTest {
+
+ private static final String TEST_RESOURCES_DIR = "test.resources.dir";
+
+ public static TestNG create() {
+ TestNG result = new TestNG();
+ result.setUseDefaultListeners(false);
+ result.setVerbose(0);
+ return result;
+ }
+
+ public static TestNG create(Class<?>... testClasses) {
+ TestNG result = create();
+ result.setTestClasses(testClasses);
+ return result;
+ }
+
+ public static String getPathToResource(String fileName) {
+ String result = System.getProperty(TEST_RESOURCES_DIR);
+ if (result == null) {
+ throw new IllegalArgumentException("System property " + TEST_RESOURCES_DIR + " was not defined.");
+ }
+ return result + File.separatorChar + fileName;
+ }
+
+ /**
+ * Compare a list of ITestResult with a list of String method names,
+ */
+ public static void assertTestResultsEqual(List<ITestResult> results, List<String> methods) {
+ List<String> resultMethods = Lists.newArrayList();
+ for (ITestResult r : results) {
+ resultMethods.add(r.getMethod().getMethodName());
+ }
+ Assert.assertEquals(resultMethods, methods);
+ }
+
+ protected TestNG create(XmlSuite... suites) {
+ TestNG result = create();
+ result.setXmlSuites(Arrays.asList(suites));
+ return result;
+ }
+
+ protected TestNG createTests(String suiteName, Class<?>... testClasses) {
+ XmlSuite suite = createXmlSuite(suiteName);
+ int i = 0;
+ for (Class<?> testClass : testClasses) {
+ createXmlTest(suite, testClass.getName() + i, testClass);
+ i++;
+ }
+ return create(suite);
+ }
+
+ protected XmlSuite createXmlSuite(String name) {
+ XmlSuite result = new XmlSuite();
+ result.setName(name);
+ return result;
+ }
+
+ protected XmlTest createXmlTest(XmlSuite suite, String name, Class clazz, Class... classes) {
+ XmlTest result = new XmlTest(suite);
+ int index = 0;
+ result.setName(name);
+ XmlClass xc = new XmlClass(clazz.getName(), index++, true /* load classes */);
+ result.getXmlClasses().add(xc);
+ for (Class c : classes) {
+ xc = new XmlClass(c.getName(), index++, true /* load classes */);
+ result.getXmlClasses().add(xc);
+ }
+
+ return result;
+ }
+
+ protected XmlTest createXmlTest(XmlSuite suite, String name, String... classes) {
+ XmlTest result = new XmlTest(suite);
+ int index = 0;
+ result.setName(name);
+ for (String c : classes) {
+ XmlClass xc = new XmlClass(c, index++, true /* load classes */);
+ result.getXmlClasses().add(xc);
+ }
+
+ return result;
+ }
+
+ protected void addMethods(XmlClass cls, String... methods) {
+ int index = 0;
+ for (String m : methods) {
+ XmlInclude include = new XmlInclude(m, index++);
+ cls.getIncludedMethods().add(include);
+ }
+ }
+
+ protected void verifyPassedTests(TestListenerAdapter tla, String... methodNames) {
+ Iterator<ITestResult> it = tla.getPassedTests().iterator();
+ Assert.assertEquals(tla.getPassedTests().size(), methodNames.length);
+
+ int i = 0;
+ while (it.hasNext()) {
+ Assert.assertEquals(it.next().getName(), methodNames[i++]);
+ }
+ }
+
+}
diff --git a/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/GitHub647.java b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/GitHub647.java
new file mode 100644
index 0000000..cc267f7
--- /dev/null
+++ b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/GitHub647.java
@@ -0,0 +1,93 @@
+package samples.testng.bugs.github647;
+
+import org.testng.IResultMap;
+import org.testng.TestListenerAdapter;
+import org.testng.TestNG;
+import org.testng.annotations.Test;
+import org.testng.xml.XmlSuite;
+import samples.testng.SimpleBaseTest;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+import static org.testng.Assert.assertEquals;
+
+public class GitHub647 extends SimpleBaseTest {
+
+ private final TestListenerAdapter tla;
+
+ public GitHub647() {
+ tla = new TestListenerAdapter();
+ }
+
+ @Test
+ public void testSkipTest() throws Exception {
+
+ final TestNG tng = createTestNG();
+
+ runTest(tng);
+
+ assertOneTestSkipped();
+ }
+
+ private TestNG createTestNG() {
+ final TestNG tng = create(SkipExceptionTest.class);
+ tng.setThreadCount(1);
+ tng.setParallel(XmlSuite.ParallelMode.NONE);
+ tng.setPreserveOrder(true);
+ tng.addListener(tla);
+ return tng;
+ }
+
+ private void assertOneTestSkipped() {
+ IResultMap skippedTests = tla.getTestContexts().get(0).getSkippedTests();
+ assertEquals(1, skippedTests.size());
+ }
+
+ private void runTest(TestNG tng) {
+
+ ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
+ ClassLoader classLoader = new SimpleClassLoader(currentClassLoader);
+
+ Thread.currentThread().setContextClassLoader(classLoader);
+
+ tng.run();
+
+ Thread.currentThread().setContextClassLoader(currentClassLoader);
+ }
+
+ public static final class SimpleClassLoader extends ClassLoader {
+
+ private final ClassLoader currentClassLoader;
+ private final URLClassLoader delegate;
+
+ public SimpleClassLoader(ClassLoader currentClassLoader) {
+ this.currentClassLoader = currentClassLoader;
+ this.delegate = new URLClassLoader(new URL[]{currentClassLoader.getResource("")}, null);
+ }
+
+
+ @Override
+ protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ final Class<?> clazz;
+
+ if (shouldBeLoadedWithDelegate(name)) {
+ clazz = delegate.loadClass(name);
+ } else {
+ clazz = currentClassLoader.loadClass(name);
+ }
+
+ if (resolve) {
+ resolveClass(clazz);
+ }
+
+ return clazz;
+ }
+
+ private boolean shouldBeLoadedWithDelegate(String name) {
+ return "org.testng.SkipException".equals(name) || "test.testng1003.SkipExceptionTest".equals(name) ||
+ "test.testng1003.SomeClass".equals(name);
+ }
+
+ }
+}
diff --git a/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SkipExceptionTest.java b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SkipExceptionTest.java
new file mode 100644
index 0000000..5c2e908
--- /dev/null
+++ b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SkipExceptionTest.java
@@ -0,0 +1,17 @@
+package samples.testng.bugs.github647;
+
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.testng.PowerMockTestCase;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+ at PrepareForTest(SomeClass.class)
+public class SkipExceptionTest extends PowerMockTestCase{
+
+ @Test
+ public void testSkipException() throws Throwable {
+ new SomeClass().throwSkipException();
+ }
+}
diff --git a/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SomeClass.java b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SomeClass.java
new file mode 100644
index 0000000..ad1bb32
--- /dev/null
+++ b/modules/module-test/testng/src/test/java/samples/testng/bugs/github647/SomeClass.java
@@ -0,0 +1,12 @@
+package samples.testng.bugs.github647;
+
+import org.testng.SkipException;
+
+/**
+ *
+ */
+public class SomeClass {
+ public void throwSkipException() {
+ throw new SkipException("Skip test");
+ }
+}
diff --git a/modules/module-test/testng/suite.xml b/modules/module-test/testng/suite.xml
new file mode 100644
index 0000000..1d7240e
--- /dev/null
+++ b/modules/module-test/testng/suite.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
+<suite name="TestNG" verbose="10" object-factory="org.powermock.modules.testng.PowerMockObjectFactory">
+ <test name="TestNG Skip test Bug #647">
+ <classes>
+ <class name="samples.testng.bugs.github647.GitHub647"/>
+ </classes>
+ </test>
+</suite>
\ No newline at end of file
diff --git a/modules/pom.xml b/modules/pom.xml
new file mode 100644
index 0000000..c20f899
--- /dev/null
+++ b/modules/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-modules</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Aggregator for building PowerMock implementation and test modules.
+ </description>
+
+ <modules>
+ <module>module-impl</module>
+ <module>module-test</module>
+ </modules>
+
+</project>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..fa5cc2e
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,392 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2011 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.sonatype.oss</groupId>
+ <artifactId>oss-parent</artifactId>
+ <version>9</version>
+ </parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <packaging>pom</packaging>
+ <version>1.6.5</version>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+ <description>
+ PowerMock allows you to unit test code normally regarded as untestable.
+ For instance it is possible to mock static methods, remove static initializers, allow mocking without dependency
+ injection and more.
+ PowerMock works by bytecode manipulation.
+ PowerMock also contain some utilities that gives you easier access to an objects internal state.
+ PowerMock can be used to test otherwise untestable code and also to achieve a cleaner separation between test
+ and production code.
+ </description>
+ <inceptionYear>2007</inceptionYear>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+ <developers>
+ <developer>
+ <id>johanhaleby</id>
+ <name>Johan Haleby</name>
+ <organization>Jayway</organization>
+ <organizationUrl>http://www.jayway.com</organizationUrl>
+ <email>johan.haleby at jayway.com</email>
+ <timezone>+1</timezone>
+ </developer>
+ <developer>
+ <id>jakr</id>
+ <name>Jan Kronquist</name>
+ <organization>Jayway</organization>
+ <organizationUrl>http://www.jayway.com</organizationUrl>
+ <email>jan.kronquist at jayway.com</email>
+ <timezone>+1</timezone>
+ </developer>
+ <developer>
+ <id>thekingnothing</id>
+ <name>Arthur Zagretdinov</name>
+ <email>arthur.zagretdinov at outlook.com</email>
+ <timezone>+3</timezone>
+ </developer>
+ </developers>
+
+ <scm>
+ <url>git at github.com:jayway/powermock.git</url>
+ <connection>scm:git:git://github.com/jayway/powermock.git</connection>
+ <developerConnection>scm:git:ssh://git@github.com/jayway/powermock.git</developerConnection>
+ </scm>
+
+ <issueManagement>
+ <system>Github</system>
+ <url>https://github.com/jayway/powermock/issues</url>
+ </issueManagement>
+ <modules>
+ <module>core</module>
+ <module>api</module>
+ <module>modules</module>
+ <module>tests</module>
+ <module>reflect</module>
+ <module>classloading</module>
+ </modules>
+ <properties>
+ <easymock.version>3.4</easymock.version>
+ <hamcrest.version>1.3</hamcrest.version>
+ <assertj.version>3.4.1</assertj.version>
+ <cglib.version>2.2.2</cglib.version>
+ <objenesis.version>2.2</objenesis.version>
+ <javaassist.version>3.20.0-GA</javaassist.version>
+ <junit.usage.version>4.12</junit.usage.version>
+ <junit.rules.version>4.8.2</junit.rules.version>
+ <testng.version>6.9.10</testng.version>
+ <xstream.version>1.4.9</xstream.version>
+ <mockito1.version>1.10.19</mockito1.version>
+ <mockito2.version>2.0.42-beta</mockito2.version>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <source>1.6</source>
+ <target>1.6</target>
+ <!-- Added because the use of sun.misc.Unsafe cause a warning message.
+ But for some reason this warning fails the build using 1.5 -->
+ <compilerArgument>-nowarn</compilerArgument>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <version>3.0.0</version>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-site-plugin</artifactId>
+ <version>3.5</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.3</version>
+ <executions>
+ <execution>
+ <id>attach-javadocs</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <failOnError>false</failOnError>
+ <additionalparam>-Xdoclint:none</additionalparam>
+ </configuration>
+ <dependencies>
+ <!-- To avoid "You have more than one version of 'org.apache.commons.logging.Log' visible, which is not allowed" -->
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <version>1.0-alpha-3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>3.0.1</version>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <instructions>
+ <Export-Package>*</Export-Package>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ <!--Letting powermock bundles to see all exported packages anywhere. Eclipse specific manifest entry. See http://www.eclipsezone.com/articles/eclipse-vms/?source=archives -->
+ <Eclipse-BuddyPolicy>global,app,ext,boot</Eclipse-BuddyPolicy>
+ <!--Letting powermock bundles to see all exported packages anywhere. OSGI standard entry. See http://wiki.osgi.org/wiki/DynamicImport-Package -->
+ <DynamicImport-Package>*</DynamicImport-Package>
+ <Bundle-Description>${project.description}</Bundle-Description>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>2.6</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.19.1</version>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+ <reporting>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <version>2.10.3</version>
+ <configuration>
+ <aggregate>true</aggregate>
+ <breakiterator>true</breakiterator>
+ <links>
+ <link>
+ http://java.sun.com/j2se/1.5.0/docs/api
+ </link>
+ </links>
+ <excludePackageNames>samples*:org.powermock.tests*:org.powermock.examples*</excludePackageNames>
+ <failOnError>false</failOnError>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-report-plugin</artifactId>
+ <version>2.19.1</version>
+ <configuration>
+ <aggregate>true</aggregate>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.5</version>
+ <reportSets>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ <report>test-aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.8.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>findbugs-maven-plugin</artifactId>
+ <version>3.0.3</version>
+ <configuration>
+ <onlyAnalyze>org.powermock.*</onlyAnalyze>
+ </configuration>
+ </plugin>
+ </plugins>
+ </reporting>
+ <profiles>
+ <profile>
+ <id>implicitDelegateAnnotation</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemProperties>
+ <powermock.implicitDelegateAnnotation>true</powermock.implicitDelegateAnnotation>
+ </systemProperties>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>defects</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/*Defect.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>testng</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <includes>
+ <include>**/org/powermock/modules/testng**/*Test.java</include>
+ </includes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ <profile>
+ <id>acceptance</id>
+ <modules>
+ <module>examples</module>
+ </modules>
+ </profile>
+ <profile>
+ <id>release</id>
+ <modules>
+ <module>release</module>
+ </modules>
+ </profile>
+ </profiles>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>${easymock.version}</version>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.objenesis</groupId>
+ <artifactId>objenesis</artifactId>
+ <version>${objenesis.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <version>${hamcrest.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <version>${cglib.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>${javaassist.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.usage.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.thoughtworks.xstream</groupId>
+ <artifactId>xstream</artifactId>
+ <version>${xstream.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <version>${testng.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/powermock.png b/powermock.png
new file mode 100644
index 0000000..17026cc
Binary files /dev/null and b/powermock.png differ
diff --git a/reflect/pom.xml b/reflect/pom.xml
new file mode 100644
index 0000000..7c269ab
--- /dev/null
+++ b/reflect/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-reflect</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Various utilities for accessing internals of a class.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.objenesis</groupId>
+ <artifactId>objenesis</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/reflect/src/main/java/org/powermock/reflect/Whitebox.java b/reflect/src/main/java/org/powermock/reflect/Whitebox.java
new file mode 100644
index 0000000..4da78b1
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/Whitebox.java
@@ -0,0 +1,857 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect;
+
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.reflect.matching.FieldMatchingStrategy;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+/**
+ * Various utilities for accessing internals of a class. Basically a simplified
+ * reflection utility intended for tests.
+ */
+public class Whitebox {
+
+ /**
+ * Convenience method to get a field from a class type.
+ * <p>
+ * The method will first try to look for a declared field in the same class.
+ * If the field is not declared in this class it will look for the field in
+ * the super class. This will continue throughout the whole class hierarchy.
+ * If the field is not found an {@link IllegalArgumentException} is thrown.
+ *
+ * @param type
+ * The type of the class where the method is located.
+ * @param fieldName
+ * The method names.
+ * @return A <code>java.lang.reflect.Field</code>.
+ * @throws FieldNotFoundException
+ * If a field cannot be found in the hierarchy.
+ */
+ public static Field getField(Class<?> type, String fieldName) {
+ return WhiteboxImpl.getField(type, fieldName);
+ }
+
+ /**
+ * Get an array of {@link Field}'s that matches the supplied list of field
+ * names.
+ *
+ * @param clazz
+ * The class that should contain the fields.
+ * @param fieldNames
+ * The names of the fields that will be returned.
+ * @return An array of Field's. May be of length 0 but not <code>null</code>
+ *
+ */
+ public static Field[] getFields(Class<?> clazz, String... fieldNames) {
+ return WhiteboxImpl.getFields(clazz, fieldNames);
+ }
+
+ /**
+ * Convenience method to get a method from a class type without having to
+ * catch the checked exceptions otherwise required. These exceptions are
+ * wrapped as runtime exceptions.
+ * <p>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link IllegalArgumentException}
+ * is thrown.
+ *
+ * @param type
+ * The type of the class where the method is located.
+ * @param methodName
+ * The method names.
+ * @param parameterTypes
+ * All parameter types of the method (may be <code>null</code>).
+ * @return A <code>java.lang.reflect.Method</code>.
+ * @throws MethodNotFoundException
+ * If a method cannot be found in the hierarchy.
+ */
+ public static Method getMethod(Class<?> type, String methodName, Class<?>... parameterTypes) {
+ return WhiteboxImpl.getMethod(type, methodName, parameterTypes);
+ }
+
+ /**
+ * Convenience method to get a method from a class type without having to
+ * catch the checked exceptions otherwise required. These exceptions are
+ * wrapped as runtime exceptions.
+ * <p>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link MethodNotFoundException}
+ * is thrown. Since the method name is not specified an
+ * {@link TooManyMethodsFoundException} is thrown if two or more methods
+ * matches the same parameter types in the same class.
+ *
+ * @param type
+ * The type of the class where the method is located.
+ * @param parameterTypes
+ * All parameter types of the method (may be <code>null</code>).
+ * @return A <code>java.lang.reflect.Method</code>.
+ * @throws MethodNotFoundException
+ * If a method cannot be found in the hierarchy.
+ * @throws TooManyMethodsFoundException
+ * If several methods were found.
+ */
+ public static Method getMethod(Class<?> type, Class<?>... parameterTypes) {
+ return WhiteboxImpl.getMethod(type, parameterTypes);
+ }
+
+ /**
+ * Create a new instance of a class without invoking its constructor.
+ * <p>
+ * No byte-code manipulation is needed to perform this operation and thus
+ * it's not necessary use the <code>PowerMockRunner</code> or
+ * <code>PrepareForTest</code> annotation to use this functionality.
+ *
+ * @param <T>
+ * The type of the instance to create.
+ * @param classToInstantiate
+ * The type of the instance to create.
+ * @return A new instance of type T, created without invoking the
+ * constructor.
+ */
+ public static <T> T newInstance(Class<T> classToInstantiate) {
+ return WhiteboxImpl.newInstance(classToInstantiate);
+ }
+
+ /**
+ * Convenience method to get a (declared) constructor from a class type
+ * without having to catch the checked exceptions otherwise required. These
+ * exceptions are wrapped as runtime exceptions. The constructor is also set
+ * to accessible.
+ *
+ * @param type
+ * The type of the class where the constructor is located.
+ * @param parameterTypes
+ * All parameter types of the constructor (may be
+ * <code>null</code>).
+ * @return A <code>java.lang.reflect.Constructor</code>.
+ * @throws ConstructorNotFoundException
+ * if the constructor cannot be found.
+ */
+ public static <T> Constructor<T> getConstructor(Class<?> type, Class<?>... parameterTypes) {
+ return (Constructor<T>) WhiteboxImpl.getConstructor(type, parameterTypes);
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until a field with name <tt>fieldName</tt> is
+ * found.
+ *
+ * @param object
+ * the object whose field to modify
+ * @param fieldName
+ * the name of the field
+ * @param value
+ * the new value of the field
+ */
+ public static void setInternalState(Object object, String fieldName, Object value) {
+ WhiteboxImpl.setInternalState(object, fieldName, value);
+ }
+
+ /**
+ * Set an array value of a field using reflection. This method will traverse
+ * the super class hierarchy until a field with name <tt>fieldName</tt> is
+ * found.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldName
+ * the name of the field
+ * @param value
+ * the new value of the field
+ */
+ public static void setInternalState(Object object, String fieldName, Object[] value) {
+ WhiteboxImpl.setInternalState(object, fieldName, value);
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until the first field assignable to the
+ * <tt>value</tt> type is found. The <tt>value</tt> (or
+ * <tt>additionaValues</tt> if present) will then be assigned to this field.
+ *
+ * @param object
+ * the object to modify
+ * @param value
+ * the new value of the field
+ * @param additionalValues
+ * Additional values to set on the object
+ */
+ public static void setInternalState(Object object, Object value, Object... additionalValues) {
+ WhiteboxImpl.setInternalState(object, value, additionalValues);
+ }
+
+ /**
+ * Set the value of a field using reflection at at specific place in the
+ * class hierarchy (<tt>where</tt>). This first field assignable to
+ * <tt>object</tt> will then be set to <tt>value</tt>.
+ *
+ * @param object
+ * the object to modify
+ * @param value
+ * the new value of the field
+ * @param where
+ * the class in the hierarchy where the field is defined
+ */
+ public static void setInternalState(Object object, Object value, Class<?> where) {
+ WhiteboxImpl.setInternalState(object, value, where);
+ }
+
+ /**
+ * Set the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. This might be useful
+ * when you have mocked the instance you are trying to modify.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldName
+ * the name of the field
+ * @param value
+ * the new value of the field
+ * @param where
+ * the class in the hierarchy where the field is defined
+ */
+ public static void setInternalState(Object object, String fieldName, Object value, Class<?> where) {
+ WhiteboxImpl.setInternalState(object, fieldName, value, where);
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until the first field of type <tt>fieldType</tt> is
+ * found. The <tt>value</tt> will then be assigned to this field.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldType
+ * the type of the field
+ * @param value
+ * the new value of the field
+ */
+ public static void setInternalState(Object object, Class<?> fieldType, Object value) {
+ WhiteboxImpl.setInternalState(object, fieldType, value);
+ }
+
+ /**
+ * Set the value of a field using reflection at a specific location (
+ * <tt>where</tt>) in the class hierarchy. The <tt>value</tt> will then be
+ * assigned to this field. The first field matching the <tt>fieldType</tt>
+ * in the hierarchy will be set.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldType
+ * the type of the field the should be set.
+ * @param value
+ * the new value of the field
+ * @param where
+ * which class in the hierarchy defining the field
+ */
+ public static void setInternalState(Object object, Class<?> fieldType, Object value, Class<?> where) {
+ WhiteboxImpl.setInternalState(object, fieldType, value, where);
+ }
+
+ /**
+ * Get the value of a field using reflection. This method will iterate
+ * through the entire class hierarchy and return the value of the first
+ * field named <tt>fieldName</tt>. If you want to get a specific field value
+ * at specific place in the class hierarchy please refer to
+ * {@link #getInternalState(Object, String, Class)}.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldName
+ * the name of the field
+ */
+ public static <T> T getInternalState(Object object, String fieldName) {
+ return WhiteboxImpl.<T> getInternalState(object, fieldName);
+ }
+
+ /**
+ * Get the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. This might be useful
+ * when you have mocked the instance you are trying to access.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldName
+ * the name of the field
+ * @param where
+ * which class the field is defined
+ */
+ public static <T> T getInternalState(Object object, String fieldName, Class<?> where) {
+ return WhiteboxImpl.<T> getInternalState(object, fieldName, where);
+ }
+
+ /**
+ * Get the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. This might be useful
+ * when you have mocked the instance you are trying to access. Use this
+ * method to avoid casting.
+ *
+ * @deprecated Use {@link #getInternalState(Object, String, Class)} instead.
+ *
+ * @param <T>
+ * the expected type of the field
+ * @param object
+ * the object to modify
+ * @param fieldName
+ * the name of the field
+ * @param where
+ * which class the field is defined
+ * @param type
+ * the expected type of the field
+ */
+ @Deprecated
+ public static <T> T getInternalState(Object object, String fieldName, Class<?> where, Class<T> type) {
+ return Whitebox.<T> getInternalState(object, fieldName, where);
+ }
+
+ /**
+ * Get the value of a field using reflection based on the fields type. This
+ * method will traverse the super class hierarchy until the first field of
+ * type <tt>fieldType</tt> is found. The value of this field will be
+ * returned.
+ *
+ * @param object
+ * the object to modify
+ * @param fieldType
+ * the type of the field
+ */
+ public static <T> T getInternalState(Object object, Class<T> fieldType) {
+ return WhiteboxImpl.<T> getInternalState(object, fieldType);
+
+ }
+
+ /**
+ * Get the value of a field using reflection based on the field type. Use
+ * this method when you need to specify in which class the field is
+ * declared. The first field matching the <tt>fieldType</tt> in
+ * <tt>where</tt> is the field whose value will be returned.
+ *
+ * @param <T>
+ * the expected type of the field
+ * @param object
+ * the object to modify
+ * @param fieldType
+ * the type of the field
+ * @param where
+ * which class the field is defined
+ */
+ public static <T> T getInternalState(Object object, Class<T> fieldType, Class<?> where) {
+ return WhiteboxImpl.<T> getInternalState(object, fieldType, where);
+ }
+
+ /**
+ * Invoke a private or inner class method without the need to specify the
+ * method name. This is thus a more refactor friendly version of the
+ * {@link #invokeMethod(Object, String, Object...)} method and is recommend
+ * over this method for that reason. This method might be useful to test
+ * private methods.
+ *
+ * @throws Throwable
+ */
+ public static synchronized <T> T invokeMethod(Object instance, Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(instance, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class static method without the need to specify
+ * the method name. This is thus a more refactor friendly version of the
+ * {@link #invokeMethod(Class, String, Object...)} method and is recommend
+ * over this method for that reason. This method might be useful to test
+ * private methods.
+ *
+ */
+ public static synchronized <T> T invokeMethod(Class<?> klass, Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(klass, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method. This might be useful to test
+ * private methods.
+ */
+ public static synchronized <T> T invokeMethod(Object instance, String methodToExecute, Object... arguments)
+ throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(instance, methodToExecute, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in cases where PowerMock cannot
+ * automatically determine the type of the parameters, for example when
+ * mixing primitive types and wrapper types in the same method. For most
+ * situations use {@link #invokeMethod(Object, Object...)} instead.
+ *
+ * @throws Exception
+ * Exception that may occur when invoking this method.
+ */
+ public static synchronized <T> T invokeMethod(Object instance, String methodToExecute, Class<?>[] argumentTypes,
+ Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(instance, methodToExecute, argumentTypes, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in a subclass (defined by
+ * <code>definedIn</code>) in cases where PowerMock cannot automatically
+ * determine the type of the parameters, for example when mixing primitive
+ * types and wrapper types in the same method. For most situations use
+ * {@link #invokeMethod(Object, Object...)} instead.
+ *
+ * @throws Exception
+ * Exception that may occur when invoking this method.
+ */
+ public static synchronized <T> T invokeMethod(Object instance, String methodToExecute, Class<?> definedIn,
+ Class<?>[] argumentTypes, Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(instance, methodToExecute, definedIn, argumentTypes, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in that is located in a subclass
+ * of the instance. This might be useful to test private methods.
+ *
+ * @throws Exception
+ * Exception that may occur when invoking this method.
+ */
+ public static synchronized <T> T invokeMethod(Object instance, Class<?> declaringClass, String methodToExecute,
+ Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(instance, declaringClass, methodToExecute, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in that is located in a subclass
+ * of the instance. This might be useful to test private methods.
+ * <p>
+ * Use this for overloaded methods.
+ *
+ * @throws Exception
+ * Exception that may occur when invoking this method.
+ */
+ public static synchronized <T> T invokeMethod(Object object, Class<?> declaringClass, String methodToExecute,
+ Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(object, declaringClass, methodToExecute, parameterTypes, arguments);
+ }
+
+ /**
+ * Invoke a static private or inner class method. This may be useful to test
+ * private methods.
+ *
+ */
+ public static synchronized <T> T invokeMethod(Class<?> clazz, String methodToExecute, Object... arguments)
+ throws Exception {
+ return WhiteboxImpl.<T> invokeMethod(clazz, methodToExecute, arguments);
+ }
+
+ /**
+ * Invoke a constructor. Useful for testing classes with a private
+ * constructor when PowerMock cannot determine which constructor to invoke.
+ * This only happens if you have two constructors with the same number of
+ * arguments where one is using primitive data types and the other is using
+ * the wrapped counter part. For example:
+ *
+ * <pre>
+ * public class MyClass {
+ * private MyClass(Integer i) {
+ * ...
+ * }
+ *
+ * private MyClass(int i) {
+ * ...
+ * }
+ * </pre>
+ *
+ * This ought to be a really rare case. So for most situation, use
+ * {@link #invokeConstructor(Class, Object...)} instead.
+ *
+ *
+ * @return The object created after the constructor has been invoked.
+ * @throws Exception
+ * If an exception occur when invoking the constructor.
+ */
+ public static <T> T invokeConstructor(Class<T> classThatContainsTheConstructorToTest, Class<?>[] parameterTypes,
+ Object[] arguments) throws Exception {
+ return WhiteboxImpl.invokeConstructor(classThatContainsTheConstructorToTest, parameterTypes, arguments);
+ }
+
+ /**
+ * Invoke a constructor. Useful for testing classes with a private
+ * constructor.
+ *
+ *
+ * @return The object created after the constructor has been invoked.
+ * @throws Exception
+ * If an exception occur when invoking the constructor.
+ */
+ public static <T> T invokeConstructor(Class<T> classThatContainsTheConstructorToTest, Object... arguments)
+ throws Exception {
+ return WhiteboxImpl.invokeConstructor(classThatContainsTheConstructorToTest, arguments);
+ }
+
+ /**
+ * Get the first parent constructor defined in a super class of
+ * <code>klass</code>.
+ *
+ * @param klass
+ * The class where the constructor is located. <code>null</code>
+ * ).
+ * @return A <code>java.lang.reflect.Constructor</code>.
+ */
+ public static Constructor<?> getFirstParentConstructor(Class<?> klass) {
+ return WhiteboxImpl.getFirstParentConstructor(klass);
+ }
+
+ /**
+ * Get an array of {@link Method}'s that matches the supplied list of method
+ * names. Both instance and static methods are taken into account.
+ *
+ * @param clazz
+ * The class that should contain the methods.
+ * @param methodNames
+ * Names of the methods that will be returned.
+ * @return An array of Method's.
+ * @throws MethodNotFoundException
+ * If no method was found.
+ */
+ public static Method[] getMethods(Class<?> clazz, String... methodNames) {
+ return WhiteboxImpl.getMethods(clazz, methodNames);
+ }
+
+ /**
+ * @return The type of the of an object.
+ */
+ public static Class<?> getType(Object object) {
+ return WhiteboxImpl.getType(object);
+ }
+
+ /**
+ * Get all fields annotated with a particular annotation. This method
+ * traverses the class hierarchy when checking for the annotation.
+ *
+ * @param object
+ * The object to look for annotations. Note that if're you're
+ * passing an object only instance fields are checked, passing a
+ * class will only check static fields.
+ * @param annotation
+ * The annotation type to look for.
+ * @param additionalAnnotations
+ * Optionally more annotations to look for. If any of the
+ * annotations are associated with a particular field it will be
+ * added to the resulting <code>Set</code>.
+ * @return A set of all fields containing the particular annotation.
+ */
+ public static Set<Field> getFieldsAnnotatedWith(Object object, Class<? extends Annotation> annotation,
+ Class<? extends Annotation>... additionalAnnotations) {
+ return WhiteboxImpl.getFieldsAnnotatedWith(object, annotation, additionalAnnotations);
+ }
+
+ /**
+ * Get all fields annotated with a particular annotation. This method
+ * traverses the class hierarchy when checking for the annotation.
+ *
+ * @param object
+ * The object to look for annotations. Note that if're you're
+ * passing an object only instance fields are checked, passing a
+ * class will only check static fields.
+ * @param annotationTypes
+ * The annotation types to look for
+ * @return A set of all fields containing the particular annotation(s).
+ * @since 1.3
+ */
+ public static Set<Field> getFieldsAnnotatedWith(Object object, Class<? extends Annotation>[] annotationTypes) {
+ return WhiteboxImpl.getFieldsAnnotatedWith(object, annotationTypes);
+ }
+
+ /**
+ * Get all instance fields for a particular object. It returns all fields
+ * regardless of the field modifier and regardless of where in the class
+ * hierarchy a field is located.
+ *
+ * @param object
+ * The object whose instance fields to get.
+ * @return All instance fields in the hierarchy. All fields are set to
+ * accessible
+ */
+ public static Set<Field> getAllInstanceFields(Object object) {
+ return WhiteboxImpl.getAllInstanceFields(object);
+ }
+
+ /**
+ * Get all static fields for a particular type.
+ *
+ * @param type
+ * The class whose static fields to get.
+ * @return All static fields in <code>type</code>. All fields are set to
+ * accessible.
+ */
+ public static Set<Field> getAllStaticFields(Class<?> type) {
+ return WhiteboxImpl.getAllStaticFields(type);
+ }
+
+ /**
+ * Get all fields assignable from a particular type. This method traverses
+ * the class hierarchy when checking for the type.
+ *
+ * @param object
+ * The object to look for type. Note that if're you're passing an
+ * object only instance fields are checked, passing a class will
+ * only check static fields.
+ * @param type
+ * The type to look for.
+ * @return A set of all fields of the particular type.
+ */
+ public static Set<Field> getFieldsOfType(Object object, Class<?> type) {
+ return WhiteboxImpl.getFieldsOfType(object, type);
+ }
+
+ /**
+ * Get an inner class type
+ *
+ * @param declaringClass
+ * The class in which the inner class is declared.
+ * @param name
+ * The unqualified name (simple name) of the inner class.
+ * @return The type.
+ */
+ public static Class<Object> getInnerClassType(Class<?> declaringClass, String name) throws ClassNotFoundException {
+ return WhiteboxImpl.getInnerClassType(declaringClass, name);
+ }
+
+ /**
+ * Get the type of a local inner class.
+ *
+ * @param declaringClass
+ * The class in which the local inner class is declared.
+ * @param occurrence
+ * The occurrence of the local class. For example if you have two
+ * local classes in the <code>declaringClass</code> you must pass
+ * in <code>1</code> if you want to get the type for the first
+ * one or <code>2</code> if you want the second one.
+ * @param name
+ * The unqualified name (simple name) of the local class.
+ * @return The type.
+ */
+ public static Class<Object> getLocalClassType(Class<?> declaringClass, int occurrence, String name)
+ throws ClassNotFoundException {
+ return WhiteboxImpl.getLocalClassType(declaringClass, occurrence, name);
+ }
+
+ /**
+ * Get the type of an anonymous inner class.
+ *
+ * @param declaringClass
+ * The class in which the anonymous inner class is declared.
+ * @param occurrence
+ * The occurrence of the anonymous inner class. For example if
+ * you have two anonymous inner classes classes in the
+ * <code>declaringClass</code> you must pass in <code>1</code> if
+ * you want to get the type for the first one or <code>2</code>
+ * if you want the second one.
+ * @return The type.
+ */
+ public static Class<Object> getAnonymousInnerClassType(Class<?> declaringClass, int occurrence)
+ throws ClassNotFoundException {
+ return WhiteboxImpl.getAnonymousInnerClassType(declaringClass, occurrence);
+ }
+
+ /**
+ * Set the values of multiple instance fields defined in a context using
+ * reflection. The values in the context will be assigned to values on the
+ * <code>instance</code>. This method will traverse the class hierarchy when
+ * searching for the fields. Example usage:
+ * <p>
+ * Given:
+ *
+ * <pre>
+ * public class MyContext {
+ * private String myString = "myString";
+ * protected int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private String myInstanceString;
+ * private int myInstanceInt;
+ *
+ * }
+ * </pre>
+ *
+ * then
+ *
+ * <pre>
+ * Whitebox.setInternalStateFromContext(new MyInstance(), new MyContext());
+ * </pre>
+ *
+ * will set the instance variables of <code>myInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ * <p>
+ * By default the {@link FieldMatchingStrategy#MATCHING} strategy is used
+ * which means that the fields defined in the context but not found in the
+ * <code>classOrInstance<code> are silently ignored.
+ *
+ *
+ *
+ * @param instance
+ * the object whose fields to modify.
+ * @param context
+ * The context where the fields are defined.
+ * @param additionalContexts
+ * Optionally more additional contexts.
+ */
+ public static void setInternalStateFromContext(Object instance, Object context, Object... additionalContexts) {
+ WhiteboxImpl.setInternalStateFromContext(instance, context, additionalContexts);
+ }
+
+ /**
+ * Set the values of multiple static fields defined in a context using
+ * reflection. The values in the context will be assigned to values on the
+ * <code>classOrInstance</code>. This method will traverse the class
+ * hierarchy when searching for the fields. Example usage:
+ * <p>
+ * Given:
+ *
+ * <pre>
+ * public class MyContext {
+ * private static String myString = "myString";
+ * protected static int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private static String myInstanceString;
+ * private static int myInstanceInt;
+ *
+ * }
+ * </pre>
+ *
+ * then
+ *
+ * <pre>
+ * Whitebox.setInternalStateFromContext(MyInstance.class, MyContext.class);
+ * </pre>
+ *
+ * will set the static variables of <code>MyInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ *<p>
+ * By default the {@link FieldMatchingStrategy#MATCHING} strategy is used
+ * which means that the fields defined in the context but not found in the
+ * <code>classOrInstance<code> are silently ignored.
+ *
+ * @param classOrInstance
+ * The object or class whose fields to set.
+ * @param context
+ * The context where the fields are defined.
+ * @param additionalContexts
+ * Optionally more additional contexts.
+ */
+ public static void setInternalStateFromContext(Object classOrInstance, Class<?> context,
+ Class<?>... additionalContexts) {
+ WhiteboxImpl.setInternalStateFromContext(classOrInstance, context, additionalContexts);
+ }
+
+ /**
+ * Set the values of multiple instance fields defined in a context using
+ * reflection and using an explicit {@link FieldMatchingStrategy}. The
+ * values in the context will be assigned to values on the
+ * <code>instance</code>. This method will traverse the class hierarchy when
+ * searching for the fields. Example usage:
+ * <p>
+ * Given:
+ *
+ * <pre>
+ * public class MyContext {
+ * private String myString = "myString";
+ * protected int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private String myInstanceString;
+ * private int myInstanceInt;
+ *
+ * }
+ * </pre>
+ *
+ * then
+ *
+ * <pre>
+ * Whitebox.setInternalStateFromContext(new MyInstance(), new MyContext());
+ * </pre>
+ *
+ * will set the instance variables of <code>myInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ *
+ * @param instance
+ * the object whose fields to modify.
+ * @param context
+ * The context where the fields are defined.
+ * @param strategy
+ * Which field matching strategy to use.
+ */
+ public static void setInternalStateFromContext(Object instance, Object context, FieldMatchingStrategy strategy) {
+ WhiteboxImpl.setInternalStateFromContext(instance, context, strategy);
+ }
+
+ /**
+ * Set the values of multiple static fields defined in a context using
+ * reflection and using an explicit {@link FieldMatchingStrategy}. The
+ * values in the context will be assigned to values on the
+ * <code>classOrInstance</code>. This method will traverse the class
+ * hierarchy when searching for the fields. Example usage:
+ * <p>
+ * Given:
+ *
+ * <pre>
+ * public class MyContext {
+ * private static String myString = "myString";
+ * protected static int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private static String myInstanceString;
+ * private static int myInstanceInt;
+ *
+ * }
+ * </pre>
+ *
+ * then
+ *
+ * <pre>
+ * Whitebox.setInternalStateFromContext(MyInstance.class, MyContext.class);
+ * </pre>
+ *
+ * will set the static variables of <code>MyInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ *<p>
+ *
+ * @param instance
+ * The object or class whose fields to set.
+ * @param context
+ * The context where the fields are defined.
+ * @param strategy
+ * Which field matching strategy to use.
+ */
+ public static void setInternalStateFromContext(Object instance, Class<?> context, FieldMatchingStrategy strategy) {
+ WhiteboxImpl.setInternalStateFromContext(instance, context, strategy);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/ConstructorNotFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/ConstructorNotFoundException.java
new file mode 100644
index 0000000..ce27b25
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/ConstructorNotFoundException.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that a constructor was
+ * not found.
+ */
+public class ConstructorNotFoundException extends RuntimeException {
+ private static final long serialVersionUID = -7329106318739007850L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public ConstructorNotFoundException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message and
+ * cause.
+ * <p>
+ * Note that the detail message associated with <code>cause</code> is
+ * <i>not</i> automatically incorporated in this exception's detail message.
+ *
+ * @param message
+ * the detail message (which is saved for later retrieval by the
+ * {@link #getMessage()} method).
+ * @param cause
+ * the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ */
+ public ConstructorNotFoundException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/FieldNotFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/FieldNotFoundException.java
new file mode 100644
index 0000000..24354b9
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/FieldNotFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that a field was not
+ * found.
+ */
+public class FieldNotFoundException extends RuntimeException {
+ private static final long serialVersionUID = 5420195402982130931L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public FieldNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/MethodInvocationException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/MethodInvocationException.java
new file mode 100644
index 0000000..44d5fae
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/MethodInvocationException.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that a method invocation
+ * failed.
+ */
+public class MethodInvocationException extends RuntimeException {
+ private static final long serialVersionUID = 4051932931902248488L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public MethodInvocationException(String message) {
+ super(message);
+ }
+
+ /**
+ * Constructs a new runtime exception with the specified detail message and
+ * cause.
+ * <p>
+ * Note that the detail message associated with <code>cause</code> is
+ * <i>not</i> automatically incorporated in this exception's detail message.
+ *
+ * @param message
+ * the detail message (which is saved for later retrieval by the
+ * {@link #getMessage()} method).
+ * @param cause
+ * the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ */
+ public MethodInvocationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ /**
+ * Constructs a new exception with the specified cause and a detail message
+ * of <tt>(cause==null ? null : cause.toString())</tt> (which typically
+ * contains the class and detail message of <tt>cause</tt>). This
+ * constructor is useful for runtime exceptions that are little more than
+ * wrappers for other throwables.
+ *
+ * @param cause
+ * the cause (which is saved for later retrieval by the
+ * {@link #getCause()} method). (A <tt>null</tt> value is
+ * permitted, and indicates that the cause is nonexistent or
+ * unknown.)
+ * @since 1.4
+ */
+ public MethodInvocationException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/MethodNotFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/MethodNotFoundException.java
new file mode 100644
index 0000000..34c02d6
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/MethodNotFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that a method was not
+ * found.
+ */
+public class MethodNotFoundException extends RuntimeException {
+ private static final long serialVersionUID = -1617211962548265914L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public MethodNotFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyConstructorsFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyConstructorsFoundException.java
new file mode 100644
index 0000000..c4567dd
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyConstructorsFoundException.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that too many
+ * constructors were found.
+ */
+public class TooManyConstructorsFoundException extends RuntimeException {
+
+ private static final long serialVersionUID = 1365925879589152290L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public TooManyConstructorsFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyFieldsFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyFieldsFoundException.java
new file mode 100644
index 0000000..ade1dab
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyFieldsFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that too many fields were
+ * found.
+ */
+public class TooManyFieldsFoundException extends RuntimeException {
+ private static final long serialVersionUID = 1564231184610341053L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public TooManyFieldsFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyMethodsFoundException.java b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyMethodsFoundException.java
new file mode 100644
index 0000000..19e53b4
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/exceptions/TooManyMethodsFoundException.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.exceptions;
+
+/**
+ * A run-time exception that may be thrown to indicate that too many methods
+ * were found.
+ */
+public class TooManyMethodsFoundException extends RuntimeException {
+ private static final long serialVersionUID = -3267907243933066607L;
+
+ /**
+ * Constructs a new exception with the specified detail message. The cause
+ * is not initialized, and may subsequently be initialized by a call to
+ * {@link #initCause}.
+ *
+ * @param message
+ * the detail message. The detail message is saved for later
+ * retrieval by the {@link #getMessage()} method.
+ */
+ public TooManyMethodsFoundException(String message) {
+ super(message);
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/CandidateConstructorSearcher.java b/reflect/src/main/java/org/powermock/reflect/internal/CandidateConstructorSearcher.java
new file mode 100644
index 0000000..b83d97e
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/CandidateConstructorSearcher.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.reflect.internal;
+
+import org.powermock.reflect.internal.comparator.ComparatorFactory;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This class search the best candidate in the given class to invoke constructor with given parameters.
+ */
+class CandidateConstructorSearcher<T> {
+ private final Class<T> classThatContainsTheConstructorToTest;
+ private final Class<?>[] argumentTypes;
+
+ public CandidateConstructorSearcher(Class<T> classThatContainsTheConstructorToTest, Class<?>[] argumentTypes) {
+
+ this.classThatContainsTheConstructorToTest = classThatContainsTheConstructorToTest;
+ this.argumentTypes = argumentTypes;
+ }
+
+ public Constructor<T> findConstructor() {
+ final Constructor<T>[] constructors = getConstructors();
+ if (constructors.length == 0) {
+ return null;
+ }
+ if (constructors.length == 1) {
+ return constructors[0];
+ } else {
+ return findBestCandidate(constructors);
+
+ }
+ }
+
+ private Constructor<T> findBestCandidate(Constructor<T>[] constructors) {
+ //We've found overloaded constructor, we need to find the best one to invoke.
+ Arrays.sort(constructors, ComparatorFactory.createConstructorComparator());
+ return constructors[0];
+ }
+
+ @SuppressWarnings("unchecked")
+ private Constructor<T>[] getConstructors() {
+
+ try {
+ Constructor<?>[] declaredConstructors = classThatContainsTheConstructorToTest.getDeclaredConstructors();
+ List<Constructor<?>> constructors = new ArrayList<Constructor<?>>();
+ for (Constructor<?> constructor : declaredConstructors) {
+ if (argumentsApplied(constructor)) {
+ constructors.add(constructor);
+ }
+ }
+ return constructors.toArray(new Constructor[constructors.size()]);
+ } catch (Exception e) {
+ return new Constructor[0];
+ }
+
+ }
+
+ private boolean argumentsApplied(Constructor<?> constructor) {
+ Class<?>[] constructorArgumentTypes = constructor.getParameterTypes();
+ if (constructorArgumentTypes.length != argumentTypes.length) {
+ return false;
+ }
+
+ for (int index = 0; index < argumentTypes.length; index++) {
+ if (!constructorArgumentTypes[index].isAssignableFrom(argumentTypes[index])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/ParameterTypesMatcher.java b/reflect/src/main/java/org/powermock/reflect/internal/ParameterTypesMatcher.java
new file mode 100644
index 0000000..5e49824
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/ParameterTypesMatcher.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.reflect.internal;
+
+/**
+ *
+ */
+class ParameterTypesMatcher {
+ private boolean isVarArgs;
+ private Class<?>[] expectedParameterTypes;
+ private Class<?>[] actualParameterTypes;
+
+ public ParameterTypesMatcher(boolean isVarArgs, Class<?>[] expectedParameterTypes, Class<?>... actualParameterTypes) {
+ this.isVarArgs = isVarArgs;
+ this.expectedParameterTypes = expectedParameterTypes;
+ this.actualParameterTypes = actualParameterTypes;
+ }
+
+ private boolean isRemainParamsVarArgs(int index, Class<?> actualParameterType) {
+ return isVarArgs && index == expectedParameterTypes.length - 1
+ && actualParameterType.getComponentType().isAssignableFrom(expectedParameterTypes[index]);
+ }
+
+ private boolean isParameterTypesNotMatch(Class<?> actualParameterType, Class<?> expectedParameterType) {
+ if (actualParameterType == null){
+ return false;
+ }
+ if (expectedParameterType == null){
+ return false;
+ }
+ return !actualParameterType.isAssignableFrom(expectedParameterType);
+ }
+
+ public boolean match() {
+ assertParametersTypesNotNull();
+ if (isParametersLengthMatch()) {
+ return false;
+ } else {
+ return isParametersMatch();
+ }
+ }
+
+ private boolean isParametersLengthMatch() {return expectedParameterTypes.length != actualParameterTypes.length;}
+
+ private void assertParametersTypesNotNull() {
+ if (expectedParameterTypes == null || actualParameterTypes == null) {
+ throw new IllegalArgumentException("parameter types cannot be null");
+ }
+ }
+
+ private Boolean isParametersMatch() {
+ for (int index = 0; index < expectedParameterTypes.length; index++) {
+ final Class<?> actualParameterType = WhiteboxImpl.getType(actualParameterTypes[index]);
+ if (isRemainParamsVarArgs(index, actualParameterType)) {
+ return true;
+ } else {
+ final Class<?> expectedParameterType = expectedParameterTypes[index];
+ if (isParameterTypesNotMatch(actualParameterType, expectedParameterType)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/TypeUtils.java b/reflect/src/main/java/org/powermock/reflect/internal/TypeUtils.java
new file mode 100644
index 0000000..860a7dd
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/TypeUtils.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal;
+
+/**
+ * Utilities for types.
+ */
+public class TypeUtils {
+
+ /**
+ * Get the default value for a type.
+ *
+ * @param type
+ * The type whose default value to get.
+ * @return The default return type of <code>type</code>.
+ */
+ public static Object getDefaultValue(Class<?> type) {
+ return getDefaultValue(type.getName());
+ }
+
+ /**
+ * Get the default value of a type with based on its fully-qualified name.
+ *
+ * @param fullyQualifiedTypeName
+ * The name of the type whose default value to get.
+ * @return The default value of <code>fullyQualifiedTypeName</code>.
+ */
+ public static Object getDefaultValue(String fullyQualifiedTypeName) {
+ if (fullyQualifiedTypeName == null) { // Void
+ return "";
+ } else if (fullyQualifiedTypeName.equals(byte.class.getName())) {
+ return (byte) 0;
+ } else if (fullyQualifiedTypeName.equals(int.class.getName())) {
+ return 0;
+ } else if (fullyQualifiedTypeName.equals(short.class.getName())) {
+ return (short) 0;
+ } else if (fullyQualifiedTypeName.equals(long.class.getName())) {
+ return 0L;
+ } else if (fullyQualifiedTypeName.equals(float.class.getName())) {
+ return 0.0F;
+ } else if (fullyQualifiedTypeName.equals(double.class.getName())) {
+ return 0.0D;
+ } else if (fullyQualifiedTypeName.equals(boolean.class.getName())) {
+ return false;
+ } else if (fullyQualifiedTypeName.equals(char.class.getName())) {
+ return ' ';
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Get the default value of a type with based on its fully-qualified name.
+ *
+ * @param fullyQualifiedTypeName
+ * The name of the type whose default value to get.
+ * @return The default value of <code>fullyQualifiedTypeName</code>.
+ */
+ public static String getDefaultValueAsString(String fullyQualifiedTypeName) {
+ if (fullyQualifiedTypeName == null) { // Void
+ return "";
+ } else if (fullyQualifiedTypeName.equals(byte.class.getName())) {
+ return "(byte) 0";
+ } else if (fullyQualifiedTypeName.equals(int.class.getName())) {
+ return "0";
+ } else if (fullyQualifiedTypeName.equals(short.class.getName())) {
+ return "(short) 0";
+ } else if (fullyQualifiedTypeName.equals(long.class.getName())) {
+ return "0L";
+ } else if (fullyQualifiedTypeName.equals(float.class.getName())) {
+ return "0.0F";
+ } else if (fullyQualifiedTypeName.equals(double.class.getName())) {
+ return "0.0D";
+ } else if (fullyQualifiedTypeName.equals(boolean.class.getName())) {
+ return "false";
+ } else if (fullyQualifiedTypeName.equals(char.class.getName())) {
+ return "' '";
+ } else {
+ return "null";
+ }
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/WhiteboxImpl.java b/reflect/src/main/java/org/powermock/reflect/internal/WhiteboxImpl.java
new file mode 100644
index 0000000..6f9453d
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/WhiteboxImpl.java
@@ -0,0 +1,2582 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal;
+
+import org.objenesis.Objenesis;
+import org.objenesis.ObjenesisStd;
+import org.objenesis.instantiator.ObjectInstantiator;
+import org.powermock.reflect.exceptions.ConstructorNotFoundException;
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+import org.powermock.reflect.exceptions.MethodInvocationException;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyConstructorsFoundException;
+import org.powermock.reflect.exceptions.TooManyFieldsFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+import org.powermock.reflect.internal.comparator.ComparatorFactory;
+import org.powermock.reflect.internal.matcherstrategies.AllFieldsMatcherStrategy;
+import org.powermock.reflect.internal.matcherstrategies.AssignableFromFieldTypeMatcherStrategy;
+import org.powermock.reflect.internal.matcherstrategies.AssignableToFieldTypeMatcherStrategy;
+import org.powermock.reflect.internal.matcherstrategies.FieldAnnotationMatcherStrategy;
+import org.powermock.reflect.internal.matcherstrategies.FieldMatcherStrategy;
+import org.powermock.reflect.internal.matcherstrategies.FieldNameMatcherStrategy;
+import org.powermock.reflect.internal.primitivesupport.BoxedWrapper;
+import org.powermock.reflect.internal.primitivesupport.PrimitiveWrapper;
+import org.powermock.reflect.matching.FieldMatchingStrategy;
+import org.powermock.reflect.spi.ProxyFramework;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Proxy;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Various utilities for accessing internals of a class. Basically a simplified
+ * reflection utility intended for tests.
+ */
+public class WhiteboxImpl {
+
+ /**
+ * The proxy framework.
+ */
+ private static ProxyFramework proxyFramework = null;
+
+ /**
+ * Convenience method to get a method from a class type without having to
+ * catch the checked exceptions otherwise required. These exceptions are
+ * wrapped as runtime exceptions.
+ * <p/>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link MethodNotFoundException}
+ * is thrown. Since the method name is not specified an
+ *
+ * @param type The type of the class where the method is located.
+ * @param parameterTypes All parameter types of the method (may be <code>null</code>).
+ * @return A . {@link TooManyMethodsFoundException} is thrown if two or more
+ * methods matches the same parameter types in the same class.
+ */
+ public static Method getMethod(Class<?> type, Class<?>... parameterTypes) {
+ Class<?> thisType = type;
+ if (parameterTypes == null) {
+ parameterTypes = new Class<?>[0];
+ }
+
+ List<Method> foundMethods = new LinkedList<Method>();
+ while (thisType != null) {
+ Method[] methodsToTraverse = null;
+ if (thisType.isInterface()) {
+ // Interfaces only contain public (and abstract) methods, no
+ // need to traverse the hierarchy.
+ methodsToTraverse = getAllPublicMethods(thisType);
+ } else {
+ methodsToTraverse = thisType.getDeclaredMethods();
+ }
+ for (Method method : methodsToTraverse) {
+ if (checkIfParameterTypesAreSame(method.isVarArgs(), parameterTypes, method.getParameterTypes())) {
+ foundMethods.add(method);
+ if (foundMethods.size() == 1) {
+ method.setAccessible(true);
+ }
+ }
+
+ }
+ if (foundMethods.size() == 1) {
+ return foundMethods.get(0);
+ } else if (foundMethods.size() > 1) {
+ break;
+ }
+ thisType = thisType.getSuperclass();
+ }
+
+ if (foundMethods.isEmpty()) {
+ throw new MethodNotFoundException("No method was found with parameter types: [ "
+ + getArgumentTypesAsString((Object[]) parameterTypes) + " ] in class "
+ + getUnmockedType(type).getName() + ".");
+ } else {
+ throwExceptionWhenMultipleMethodMatchesFound("method name",
+ foundMethods.toArray(new Method[foundMethods.size()]));
+ }
+ // Will never happen
+ return null;
+ }
+
+ /**
+ * Convenience method to get a method from a class type without having to
+ * catch the checked exceptions otherwise required. These exceptions are
+ * wrapped as runtime exceptions.
+ * <p/>
+ * The method will first try to look for a declared method in the same
+ * class. If the method is not declared in this class it will look for the
+ * method in the super class. This will continue throughout the whole class
+ * hierarchy. If the method is not found an {@link IllegalArgumentException}
+ * is thrown.
+ *
+ * @param type The type of the class where the method is located.
+ * @param methodName The method names.
+ * @param parameterTypes All parameter types of the method (may be <code>null</code>).
+ * @return A .
+ */
+ public static Method getMethod(Class<?> type, String methodName, Class<?>... parameterTypes) {
+ Class<?> thisType = type;
+ if (parameterTypes == null) {
+ parameterTypes = new Class<?>[0];
+ }
+ while (thisType != null) {
+ Method[] methodsToTraverse = null;
+ if (thisType.isInterface()) {
+ // Interfaces only contain public (and abstract) methods, no
+ // need to traverse the hierarchy.
+ methodsToTraverse = getAllPublicMethods(thisType);
+ } else {
+ methodsToTraverse = thisType.getDeclaredMethods();
+ }
+ for (Method method : methodsToTraverse) {
+ if (methodName.equals(method.getName())
+ && checkIfParameterTypesAreSame(method.isVarArgs(), parameterTypes, method.getParameterTypes())) {
+ method.setAccessible(true);
+ return method;
+ }
+ }
+ thisType = thisType.getSuperclass();
+ }
+
+ throwExceptionIfMethodWasNotFound(type, methodName, null, new Object[]{parameterTypes});
+ return null;
+ }
+
+ /**
+ * Convenience method to get a field from a class type.
+ * <p/>
+ * The method will first try to look for a declared field in the same class.
+ * If the method is not declared in this class it will look for the field in
+ * the super class. This will continue throughout the whole class hierarchy.
+ * If the field is not found an {@link IllegalArgumentException} is thrown.
+ *
+ * @param type The type of the class where the method is located.
+ * @param fieldName The method names.
+ * @return A .
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public static Field getField(Class<?> type, String fieldName) {
+ LinkedList<Class<?>> examine = new LinkedList<Class<?>>();
+ examine.add(type);
+ Set<Class<?>> done = new HashSet<Class<?>>();
+ while (examine.isEmpty() == false) {
+ Class<?> thisType = examine.removeFirst();
+ done.add(thisType);
+ final Field[] declaredField = thisType.getDeclaredFields();
+ for (Field field : declaredField) {
+ if (fieldName.equals(field.getName())) {
+ field.setAccessible(true);
+ return field;
+ }
+ }
+ Set<Class<?>> potential = new HashSet<Class<?>>();
+ final Class<?> clazz = thisType.getSuperclass();
+ if (clazz != null) {
+ potential.add(thisType.getSuperclass());
+ }
+ potential.addAll((Collection) Arrays.asList(thisType.getInterfaces()));
+ potential.removeAll(done);
+ examine.addAll(potential);
+ }
+
+ throwExceptionIfFieldWasNotFound(type, fieldName, null);
+ return null;
+ }
+
+ /**
+ * Create a new instance of a class without invoking its constructor.
+ * <p/>
+ * No byte-code manipulation is needed to perform this operation and thus
+ * it's not necessary use the <code>PowerMockRunner</code> or
+ * <code>PrepareForTest</code> annotation to use this functionality.
+ *
+ * @param <T> The type of the instance to create.
+ * @param classToInstantiate The type of the instance to create.
+ * @return A new instance of type T, created without invoking the
+ * constructor.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T newInstance(Class<T> classToInstantiate) {
+ int modifiers = classToInstantiate.getModifiers();
+
+ final Object object;
+ if (Modifier.isInterface(modifiers)) {
+ object = Proxy.newProxyInstance(WhiteboxImpl.class.getClassLoader(), new Class<?>[]{classToInstantiate},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ return TypeUtils.getDefaultValue(method.getReturnType());
+ }
+ });
+ } else if (classToInstantiate.isArray()) {
+ object = Array.newInstance(classToInstantiate.getComponentType(), 0);
+ } else if (Modifier.isAbstract(modifiers)) {
+ throw new IllegalArgumentException(
+ "Cannot instantiate an abstract class. Please use the ConcreteClassGenerator in PowerMock support to generate a concrete class first.");
+ } else {
+ Objenesis objenesis = new ObjenesisStd();
+ ObjectInstantiator thingyInstantiator = objenesis.getInstantiatorOf(classToInstantiate);
+ object = thingyInstantiator.newInstance();
+ }
+ return (T) object;
+ }
+
+ /**
+ * Convenience method to get a (declared) constructor from a class type
+ * without having to catch the checked exceptions otherwise required. These
+ * exceptions are wrapped as runtime exceptions. The constructor is also set
+ * to accessible.
+ *
+ * @param type The type of the class where the constructor is located.
+ * @param parameterTypes All parameter types of the constructor (may be
+ * <code>null</code>).
+ * @return A .
+ */
+ public static Constructor<?> getConstructor(Class<?> type, Class<?>... parameterTypes) {
+ Class<?> unmockedType = WhiteboxImpl.getUnmockedType(type);
+ try {
+ final Constructor<?> constructor = unmockedType.getDeclaredConstructor(parameterTypes);
+ constructor.setAccessible(true);
+ return constructor;
+ } catch (RuntimeException e) {
+ throw (RuntimeException) e;
+ } catch (Error e) {
+ throw (Error) e;
+ } catch (Throwable e) {
+ throw new ConstructorNotFoundException(String.format(
+ "Failed to lookup constructor with parameter types [ %s ] in class %s.",
+ getArgumentTypesAsString((Object[]) parameterTypes), unmockedType.getName()), e);
+ }
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until a field with name <tt>fieldName</tt> is
+ * found.
+ *
+ * @param object the object whose field to modify
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ */
+ public static void setInternalState(Object object, String fieldName, Object value) {
+ Field foundField = findFieldInHierarchy(object, fieldName);
+ setField(object, value, foundField);
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until a field with name <tt>fieldName</tt> is
+ * found.
+ *
+ * @param object the object to modify
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ */
+ public static void setInternalState(Object object, String fieldName, Object[] value) {
+ setInternalState(object, fieldName, (Object) value);
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until the first field of type <tt>fieldType</tt> is
+ * found. The <tt>value</tt> will then be assigned to this field.
+ *
+ * @param object the object to modify
+ * @param fieldType the type of the field
+ * @param value the new value of the field
+ */
+ public static void setInternalState(Object object, Class<?> fieldType, Object value) {
+ setField(object, value, findFieldInHierarchy(object, new AssignableFromFieldTypeMatcherStrategy(fieldType)));
+ }
+
+ /**
+ * Set the value of a field using reflection. This method will traverse the
+ * super class hierarchy until the first field assignable to the
+ * <tt>value</tt> type is found. The <tt>value</tt> (or
+ * <tt>additionaValues</tt> if present) will then be assigned to this field.
+ *
+ * @param object the object to modify
+ * @param value the new value of the field
+ * @param additionalValues Additional values to set on the object
+ */
+ public static void setInternalState(Object object, Object value, Object... additionalValues) {
+ setField(object, value,
+ findFieldInHierarchy(object, new AssignableFromFieldTypeMatcherStrategy(getType(value))));
+ if (additionalValues != null && additionalValues.length > 0) {
+ for (Object additionalValue : additionalValues) {
+ setField(
+ object,
+ additionalValue,
+ findFieldInHierarchy(object, new AssignableFromFieldTypeMatcherStrategy(
+ getType(additionalValue))));
+ }
+ }
+ }
+
+ /**
+ * Set the value of a field using reflection at at specific place in the
+ * class hierarchy (<tt>where</tt>). This first field assignable to
+ * <tt>object</tt> will then be set to <tt>value</tt>.
+ *
+ * @param object the object to modify
+ * @param value the new value of the field
+ * @param where the class in the hierarchy where the field is defined
+ */
+ public static void setInternalState(Object object, Object value, Class<?> where) {
+ setField(object, value, findField(object, new AssignableFromFieldTypeMatcherStrategy(getType(value)), where));
+ }
+
+ /**
+ * Set the value of a field using reflection at a specific location (
+ * <tt>where</tt>) in the class hierarchy. The <tt>value</tt> will then be
+ * assigned to this field.
+ *
+ * @param object the object to modify
+ * @param fieldType the type of the field the should be set.
+ * @param value the new value of the field
+ * @param where which class in the hierarchy defining the field
+ */
+ public static void setInternalState(Object object, Class<?> fieldType, Object value, Class<?> where) {
+ if (fieldType == null || where == null) {
+ throw new IllegalArgumentException("fieldType and where cannot be null");
+ }
+
+ setField(object, value, findFieldOrThrowException(fieldType, where));
+ }
+
+ /**
+ * Set the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. This is useful if you
+ * have two fields in a class hierarchy that has the same name but you like
+ * to modify the latter.
+ *
+ * @param object the object to modify
+ * @param fieldName the name of the field
+ * @param value the new value of the field
+ * @param where which class the field is defined
+ */
+ public static void setInternalState(Object object, String fieldName, Object value, Class<?> where) {
+ if (object == null || fieldName == null || fieldName.equals("") || fieldName.startsWith(" ")) {
+ throw new IllegalArgumentException("object, field name, and \"where\" must not be empty or null.");
+ }
+
+ final Field field = getField(fieldName, where);
+ try {
+ field.set(object, value);
+ } catch (Exception e) {
+ throw new RuntimeException("Internal Error: Failed to set field in method setInternalState.", e);
+ }
+ }
+
+ /**
+ * Get the value of a field using reflection. This method will iterate
+ * through the entire class hierarchy and return the value of the first
+ * field named <tt>fieldName</tt>. If you want to get a specific field value
+ * at specific place in the class hierarchy please refer to
+ *
+ * @param <T> the generic type
+ * @param object the object to modify
+ * @param fieldName the name of the field
+ * @return the internal state
+ * {@link #getInternalState(Object, String, Class)}.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getInternalState(Object object, String fieldName) {
+ Field foundField = findFieldInHierarchy(object, fieldName);
+ try {
+ return (T) foundField.get(object);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Internal error: Failed to get field in method getInternalState.", e);
+ }
+ }
+
+ /**
+ * Find field in hierarchy.
+ *
+ * @param object the object
+ * @param fieldName the field name
+ * @return the field
+ */
+ private static Field findFieldInHierarchy(Object object, String fieldName) {
+ return findFieldInHierarchy(object, new FieldNameMatcherStrategy(fieldName));
+ }
+
+ /**
+ * Find field in hierarchy.
+ *
+ * @param object the object
+ * @param strategy the strategy
+ * @return the field
+ */
+ private static Field findFieldInHierarchy(Object object, FieldMatcherStrategy strategy) {
+ assertObjectInGetInternalStateIsNotNull(object);
+ return findSingleFieldUsingStrategy(strategy, object, true, getType(object));
+ }
+
+ /**
+ * Find field.
+ *
+ * @param object the object
+ * @param strategy the strategy
+ * @param where the where
+ * @return the field
+ */
+ private static Field findField(Object object, FieldMatcherStrategy strategy, Class<?> where) {
+ return findSingleFieldUsingStrategy(strategy, object, false, where);
+ }
+
+ /**
+ * Find single field using strategy.
+ *
+ * @param strategy the strategy
+ * @param object the object
+ * @param checkHierarchy the check hierarchy
+ * @param startClass the start class
+ * @return the field
+ */
+ private static Field findSingleFieldUsingStrategy(FieldMatcherStrategy strategy, Object object,
+ boolean checkHierarchy, Class<?> startClass) {
+ assertObjectInGetInternalStateIsNotNull(object);
+ Field foundField = null;
+ final Class<?> originalStartClass = startClass;
+ while (startClass != null) {
+ final Field[] declaredFields = startClass.getDeclaredFields();
+ for (Field field : declaredFields) {
+ if (strategy.matches(field) && hasFieldProperModifier(object, field)) {
+ if (foundField != null) {
+ throw new TooManyFieldsFoundException("Two or more fields matching " + strategy + ".");
+ }
+ foundField = field;
+ }
+ }
+ if (foundField != null) {
+ break;
+ } else if (checkHierarchy == false) {
+ break;
+ }
+ startClass = startClass.getSuperclass();
+ }
+ if (foundField == null) {
+ strategy.notFound(originalStartClass, !isClass(object));
+ }
+ foundField.setAccessible(true);
+ return foundField;
+ }
+
+ /**
+ * Find all fields using strategy.
+ *
+ * @param strategy the strategy
+ * @param object the object
+ * @param checkHierarchy the check hierarchy
+ * @param startClass the start class
+ * @return the set
+ */
+ private static Set<Field> findAllFieldsUsingStrategy(FieldMatcherStrategy strategy, Object object,
+ boolean checkHierarchy, Class<?> startClass) {
+ assertObjectInGetInternalStateIsNotNull(object);
+ final Set<Field> foundFields = new LinkedHashSet<Field>();
+ while (startClass != null) {
+ final Field[] declaredFields = startClass.getDeclaredFields();
+ for (Field field : declaredFields) {
+ if (strategy.matches(field) && hasFieldProperModifier(object, field)) {
+ field.setAccessible(true);
+ foundFields.add(field);
+ }
+ }
+ if (!checkHierarchy) {
+ break;
+ }
+ startClass = startClass.getSuperclass();
+ }
+
+ return Collections.unmodifiableSet(foundFields);
+ }
+
+ /**
+ * Checks for field proper modifier.
+ *
+ * @param object the object
+ * @param field the field
+ * @return true, if successful
+ */
+ private static boolean hasFieldProperModifier(Object object, Field field) {
+ return ((object instanceof Class<?> && Modifier.isStatic(field.getModifiers())) || ((object instanceof Class<?> == false && Modifier
+ .isStatic(field.getModifiers()) == false)));
+ }
+
+ /**
+ * Get the value of a field using reflection. This method will traverse the
+ * super class hierarchy until the first field of type <tt>fieldType</tt> is
+ * found. The value of this field will be returned.
+ *
+ * @param <T> the generic type
+ * @param object the object to modify
+ * @param fieldType the type of the field
+ * @return the internal state
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getInternalState(Object object, Class<T> fieldType) {
+ Field foundField = findFieldInHierarchy(object, new AssignableToFieldTypeMatcherStrategy(fieldType));
+ try {
+ return (T) foundField.get(object);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Internal error: Failed to get field in method getInternalState.", e);
+ }
+ }
+
+ /**
+ * Get the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. The first field matching
+ * the <tt>fieldType</tt> in <tt>where</tt> will is the field whose value
+ * will be returned.
+ *
+ * @param <T> the expected type of the field
+ * @param object the object to modify
+ * @param fieldType the type of the field
+ * @param where which class the field is defined
+ * @return the internal state
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getInternalState(Object object, Class<T> fieldType, Class<?> where) {
+ if (object == null) {
+ throw new IllegalArgumentException("object and type are not allowed to be null");
+ }
+
+ try {
+ return (T) findFieldOrThrowException(fieldType, where).get(object);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Internal error: Failed to get field in method getInternalState.", e);
+ }
+ }
+
+ /**
+ * Get the value of a field using reflection. Use this method when you need
+ * to specify in which class the field is declared. This might be useful
+ * when you have mocked the instance you are trying to access. Use this
+ * method to avoid casting.
+ *
+ * @param <T> the expected type of the field
+ * @param object the object to modify
+ * @param fieldName the name of the field
+ * @param where which class the field is defined
+ * @return the internal state
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getInternalState(Object object, String fieldName, Class<?> where) {
+ if (object == null || fieldName == null || fieldName.equals("") || fieldName.startsWith(" ")) {
+ throw new IllegalArgumentException("object, field name, and \"where\" must not be empty or null.");
+ }
+
+ Field field = null;
+ try {
+ field = where.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ return (T) field.get(object);
+ } catch (NoSuchFieldException e) {
+ throw new FieldNotFoundException("Field '" + fieldName + "' was not found in class " + where.getName()
+ + ".");
+ } catch (Exception e) {
+ throw new RuntimeException("Internal error: Failed to get field in method getInternalState.", e);
+ }
+ }
+
+ /**
+ * Invoke a private or inner class method without the need to specify the
+ * method name. This is thus a more refactor friendly version of the
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ * {@link #invokeMethod(Object, String, Object...)} method and
+ * is recommend over this method for that reason. This method
+ * might be useful to test private methods.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object tested, Object... arguments) throws Exception {
+ return (T) doInvokeMethod(tested, null, null, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method without the need to specify the
+ * method name. This is thus a more refactor friendly version of the
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ * {@link #invokeMethod(Object, String, Object...)} method and
+ * is recommend over this method for that reason. This method
+ * might be useful to test private methods.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Class<?> tested, Object... arguments) throws Exception {
+ return (T) doInvokeMethod(tested, null, null, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method. This might be useful to test
+ * private methods.
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param methodToExecute the method to execute
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object tested, String methodToExecute, Object... arguments)
+ throws Exception {
+ return (T) doInvokeMethod(tested, null, methodToExecute, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in cases where power mock cannot
+ * automatically determine the type of the parameters, for example when
+ * mixing primitive types and wrapper types in the same method. For most
+ * situations use {@link #invokeMethod(Class, String, Object...)} instead.
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param methodToExecute the method to execute
+ * @param argumentTypes the argument types
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception Exception that may occur when invoking this method.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object tested, String methodToExecute, Class<?>[] argumentTypes,
+ Object... arguments) throws Exception {
+ final Class<?> unmockedType = getType(tested);
+ Method method = getMethod(unmockedType, methodToExecute, argumentTypes);
+ if (method == null) {
+ throwExceptionIfMethodWasNotFound(unmockedType, methodToExecute, null, arguments);
+ }
+ return (T) performMethodInvocation(tested, method, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in a subclass (defined by
+ * <code>definedIn</code>) in cases where power mock cannot automatically
+ * determine the type of the parameters, for example when mixing primitive
+ * types and wrapper types in the same method. For most situations use
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param methodToExecute the method to execute
+ * @param definedIn the defined in
+ * @param argumentTypes the argument types
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception Exception that may occur when invoking this method.
+ * {@link #invokeMethod(Class, String, Object...)} instead.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object tested, String methodToExecute, Class<?> definedIn,
+ Class<?>[] argumentTypes, Object... arguments) throws Exception {
+ Method method = getMethod(definedIn, methodToExecute, argumentTypes);
+ if (method == null) {
+ throwExceptionIfMethodWasNotFound(definedIn, methodToExecute, null, arguments);
+ }
+ return (T) performMethodInvocation(tested, method, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method in that is located in a subclass
+ * of the tested instance. This might be useful to test private methods.
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param declaringClass the declaring class
+ * @param methodToExecute the method to execute
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception Exception that may occur when invoking this method.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object tested, Class<?> declaringClass, String methodToExecute,
+ Object... arguments) throws Exception {
+ return (T) doInvokeMethod(tested, declaringClass, methodToExecute, arguments);
+ }
+
+ /**
+ * Invoke a private method in that is located in a subclass of an instance.
+ * This might be useful to test overloaded private methods.
+ * <p/>
+ * Use this for overloaded methods only, if possible use
+ *
+ * @param <T> the generic type
+ * @param object the object
+ * @param declaringClass the declaring class
+ * @param methodToExecute the method to execute
+ * @param parameterTypes the parameter types
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception Exception that may occur when invoking this method.
+ * {@link #invokeMethod(Object, Object...)} or
+ * {@link #invokeMethod(Object, String, Object...)} instead.
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Object object, Class<?> declaringClass, String methodToExecute,
+ Class<?>[] parameterTypes, Object... arguments) throws Exception {
+ if (object == null) {
+ throw new IllegalArgumentException("object cannot be null");
+ }
+
+ final Method methodToInvoke = getMethod(declaringClass, methodToExecute, parameterTypes);
+ // Invoke method
+ return (T) performMethodInvocation(object, methodToInvoke, arguments);
+ }
+
+ /**
+ * Invoke a private or inner class method. This might be useful to test
+ * private methods.
+ *
+ * @param <T> the generic type
+ * @param clazz the clazz
+ * @param methodToExecute the method to execute
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ */
+ @SuppressWarnings("unchecked")
+ public static synchronized <T> T invokeMethod(Class<?> clazz, String methodToExecute, Object... arguments)
+ throws Exception {
+ return (T) doInvokeMethod(clazz, null, methodToExecute, arguments);
+ }
+
+ /**
+ * Do invoke method.
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param declaringClass the declaring class
+ * @param methodToExecute the method to execute
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ */
+ @SuppressWarnings("unchecked")
+ private static <T> T doInvokeMethod(Object tested, Class<?> declaringClass, String methodToExecute,
+ Object... arguments) throws Exception {
+ Method methodToInvoke = findMethodOrThrowException(tested, declaringClass, methodToExecute, arguments);
+
+ // Invoke test
+ return (T) performMethodInvocation(tested, methodToInvoke, arguments);
+ }
+
+ /**
+ * Finds and returns a certain method. If the method couldn't be found this
+ * method delegates to
+ *
+ * @param tested The instance or class containing the method.
+ * @param declaringClass The class where the method is supposed to be declared (may be
+ * <code>null</code>).
+ * @param methodToExecute The method name. If <code>null</code> then method will be
+ * looked up based on the argument types only.
+ * @param arguments The arguments of the methods.
+ * @return A single method.
+ * @throws {@link org.powermock.reflect.exceptions.MethodNotFoundException} if no method was found
+ * @throws {@link org.powermock.reflect.exceptions.TooManyMethodsFoundException} if too methods matched
+ */
+ public static Method findMethodOrThrowException(Object tested, Class<?> declaringClass, String methodToExecute,
+ Object[] arguments) {
+ if (tested == null) {
+ throw new IllegalArgumentException("The object to perform the operation on cannot be null.");
+ }
+
+ /*
+ * Get methods from the type if it's not mocked or from the super type
+ * if the tested object is mocked.
+ */
+ Class<?> testedType = null;
+ if (isClass(tested)) {
+ testedType = (Class<?>) tested;
+ } else {
+ testedType = tested.getClass();
+ }
+
+ Method[] methods = null;
+ if (declaringClass == null) {
+ methods = getAllMethods(testedType);
+ } else {
+ methods = declaringClass.getDeclaredMethods();
+ }
+ Method potentialMethodToInvoke = null;
+ for (Method method : methods) {
+ if (methodToExecute == null || method.getName().equals(methodToExecute)) {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ if ((arguments != null && (paramTypes.length == arguments.length))) {
+ if (paramTypes.length == 0) {
+ potentialMethodToInvoke = method;
+ break;
+ }
+ boolean methodFound = checkArgumentTypesMatchParameterTypes(method.isVarArgs(), paramTypes, arguments);
+ if (methodFound) {
+ if (potentialMethodToInvoke == null) {
+ potentialMethodToInvoke = method;
+ } else if (potentialMethodToInvoke.getName().equals(method.getName())) {
+ if (areAllArgumentsOfSameType(arguments) && potentialMethodToInvoke.getDeclaringClass() != method.getDeclaringClass()) {
+ // We've already found the method which means that "potentialMethodToInvoke" overrides "method".
+ return potentialMethodToInvoke;
+ } else {
+ // We've found an overloaded method
+ return getBestMethodCandidate(getType(tested), method.getName(), getTypes(arguments), false);
+ }
+ } else {
+ // A special case to be backward compatible
+ Method bestCandidateMethod = getMethodWithMostSpecificParameterTypes(method, potentialMethodToInvoke);
+ if (bestCandidateMethod != null) {
+ potentialMethodToInvoke = bestCandidateMethod;
+ continue;
+ }
+ /*
+ * We've already found a method match before, this
+ * means that PowerMock cannot determine which
+ * method to expect since there are two methods with
+ * the same name and the same number of arguments
+ * but one is using wrapper types.
+ */
+ throwExceptionWhenMultipleMethodMatchesFound("argument parameter types", new Method[]{
+ potentialMethodToInvoke, method});
+ }
+ }
+ } else if (isPotentialVarArgsMethod(method, arguments)) {
+ if (potentialMethodToInvoke == null) {
+ potentialMethodToInvoke = method;
+ } else {
+ /*
+ * We've already found a method match before, this means
+ * that PowerMock cannot determine which method to
+ * expect since there are two methods with the same name
+ * and the same number of arguments but one is using
+ * wrapper types.
+ */
+ throwExceptionWhenMultipleMethodMatchesFound("argument parameter types", new Method[]{
+ potentialMethodToInvoke, method});
+ }
+ break;
+ } else if (arguments != null && (paramTypes.length != arguments.length)) {
+ continue;
+ } else if (arguments == null && paramTypes.length == 1 && !paramTypes[0].isPrimitive()) {
+ potentialMethodToInvoke = method;
+ }
+ }
+ }
+
+ WhiteboxImpl.throwExceptionIfMethodWasNotFound(getType(tested), methodToExecute, potentialMethodToInvoke,
+ arguments);
+ return potentialMethodToInvoke;
+ }
+
+ /**
+ * Find the method whose parameter types most closely matches the <code>types</code>.
+ *
+ * @param firstMethodCandidate The first method candidate
+ * @param secondMethodCandidate The second method candidate
+ * @return The method that most closely matches the provided types or <code>null</code> if no method match.
+ */
+ private static Method getMethodWithMostSpecificParameterTypes(Method firstMethodCandidate, Method secondMethodCandidate) {
+ Class<?>[] firstMethodCandidateParameterTypes = firstMethodCandidate.getParameterTypes();
+ Class<?>[] secondMethodCandidateParameterTypes = secondMethodCandidate.getParameterTypes();
+
+ Method bestMatch = null;
+ for (int i = 0; i < firstMethodCandidateParameterTypes.length; i++) {
+ Class<?> candidateType1 = toBoxedIfPrimitive(firstMethodCandidateParameterTypes[i]);
+ Class<?> candidateType2 = toBoxedIfPrimitive(secondMethodCandidateParameterTypes[i]);
+
+ if (!candidateType1.equals(candidateType2)) {
+ Method potentialMatch = null;
+ if (candidateType1.isAssignableFrom(candidateType2)) {
+ potentialMatch = secondMethodCandidate;
+ } else if (candidateType2.isAssignableFrom(candidateType1)) {
+ potentialMatch = firstMethodCandidate;
+ }
+
+ if (potentialMatch != null) {
+ if (bestMatch != null && !potentialMatch.equals(bestMatch)) {
+ /*
+ * We cannot determine which method is the most specific because one parameter of the first candidate
+ * was more specific and another parameter of the second candidate was more specific.
+ */
+ return null;
+ } else {
+ bestMatch = potentialMatch;
+ }
+ }
+ }
+ }
+
+ return bestMatch;
+ }
+
+ private static Class<?> toBoxedIfPrimitive(Class<?> type) {
+ return type.isPrimitive() ? BoxedWrapper.getBoxedFromPrimitiveType(type) : type;
+ }
+
+ /**
+ * Gets the types.
+ *
+ * @param arguments the arguments
+ * @return the types
+ */
+ private static Class<?>[] getTypes(Object[] arguments) {
+ Class<?>[] classes = new Class<?>[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ classes[i] = getType(arguments[i]);
+ }
+ return classes;
+ }
+
+ /**
+ * Gets the best method candidate.
+ *
+ * @param cls the cls
+ * @param methodName the method name
+ * @param signature the signature
+ * @param exactParameterTypeMatch <code>true</code> if the <code>expectedTypes</code> must match
+ * the parameter types must match exactly, <code>false</code> if
+ * the <code>expectedTypes</code> are allowed to be converted
+ * into primitive types if they are of a wrapped type and still
+ * match.
+ * @return the best method candidate
+ */
+ public static Method getBestMethodCandidate(Class<?> cls, String methodName, Class<?>[] signature,
+ boolean exactParameterTypeMatch) {
+ final Method foundMethod;
+ final Method[] methods = getMethods(cls, methodName, signature, exactParameterTypeMatch);
+ if (methods.length == 1) {
+ foundMethod = methods[0];
+ } else {
+ // We've found overloaded methods, we need to find the best one to invoke.
+ Arrays.sort(methods, ComparatorFactory.createMethodComparator());
+ foundMethod = methods[0];
+ }
+ return foundMethod;
+ }
+
+ /**
+ * Finds and returns the default constructor. If the constructor couldn't be
+ * found this method delegates to {@link #throwExceptionWhenMultipleConstructorMatchesFound(java.lang.reflect.Constructor[])}.
+ *
+ * @param type The type where the constructor should be located.
+ * @return The found constructor.
+ * @throws {@link org.powermock.reflect.exceptions.TooManyConstructorsFoundException} if too many constructors was found.
+ */
+ public static Constructor<?> findDefaultConstructorOrThrowException(Class<?> type) {
+ if (type == null) {
+ throw new IllegalArgumentException("type cannot be null");
+ }
+
+ final Constructor<?> declaredConstructor;
+ try {
+ declaredConstructor = type.getDeclaredConstructor();
+ } catch (NoSuchMethodException e) {
+ throw new ConstructorNotFoundException(String.format("Couldn't find a default constructor in %s.", type.getName()));
+ }
+ return declaredConstructor;
+ }
+
+ /**
+ * Finds and returns any constructor. If the constructor couldn't be
+ * found this method delegates to {@link #throwExceptionWhenMultipleConstructorMatchesFound(java.lang.reflect.Constructor[])}.
+ *
+ * @param type The type where the constructor should be located.
+ * @return The found constructor.
+ * @throws {@link org.powermock.reflect.exceptions.TooManyConstructorsFoundException} if too many constructors was found.
+ */
+ public static Constructor<?> findConstructorOrThrowException(Class<?> type) {
+ final Constructor<?>[] declaredConstructors = filterPowerMockConstructor(type.getDeclaredConstructors());
+ if (declaredConstructors.length > 1) {
+ throwExceptionWhenMultipleConstructorMatchesFound(declaredConstructors);
+ }
+ return declaredConstructors[0];
+ }
+
+ /**
+ * Filter power mock constructor.
+ *
+ * @param declaredConstructors the declared constructors
+ * @return the constructor[]
+ */
+ private static Constructor<?>[] filterPowerMockConstructor(Constructor<?>[] declaredConstructors) {
+ Set<Constructor<?>> constructors = new HashSet<Constructor<?>>();
+ for (Constructor<?> constructor : declaredConstructors) {
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ if (parameterTypes.length >= 1
+ && parameterTypes[parameterTypes.length - 1].getName().equals(
+ "org.powermock.core.IndicateReloadClass")) {
+ continue;
+ } else {
+ constructors.add(constructor);
+ }
+ }
+ return constructors.toArray(new Constructor<?>[constructors.size()]);
+ }
+
+ /**
+ * Finds and returns a certain constructor. If the constructor couldn't be
+ * found this method delegates to
+ *
+ * @param type The type where the constructor should be located.
+ * @param arguments The arguments passed to the constructor.
+ * @return The found constructor.
+ * @throws {@link org.powermock.reflect.exceptions.ConstructorNotFoundException} if no constructor was found
+ * @throws {@link org.powermock.reflect.exceptions.TooManyConstructorsFoundException} if too constructors matched
+ */
+ public static Constructor<?> findUniqueConstructorOrThrowException(Class<?> type, Object... arguments) {
+ if (type == null) {
+ throw new IllegalArgumentException("Class type cannot be null.");
+ }
+
+ Class<?> unmockedType = getUnmockedType(type);
+ if ((unmockedType.isLocalClass() || unmockedType.isAnonymousClass() || unmockedType.isMemberClass())
+ && !Modifier.isStatic(unmockedType.getModifiers()) && arguments != null) {
+ Object[] argumentsForLocalClass = new Object[arguments.length + 1];
+ argumentsForLocalClass[0] = unmockedType.getEnclosingClass();
+ System.arraycopy(arguments, 0, argumentsForLocalClass, 1, arguments.length);
+ arguments = argumentsForLocalClass;
+ }
+
+ Constructor<?>[] constructors = filterPowerMockConstructor(unmockedType.getDeclaredConstructors());
+ Constructor<?> potentialConstructor = null;
+ for (Constructor<?> constructor : constructors) {
+ Class<?>[] paramTypes = constructor.getParameterTypes();
+ if ((arguments != null && (paramTypes.length == arguments.length))) {
+ if (paramTypes.length == 0) {
+ potentialConstructor = constructor;
+ break;
+ }
+ boolean constructorFound = checkArgumentTypesMatchParameterTypes(constructor.isVarArgs(), paramTypes, arguments);
+ if (constructorFound) {
+ if (potentialConstructor == null) {
+ potentialConstructor = constructor;
+ } else {
+ /*
+ * We've already found a constructor match before, this
+ * means that PowerMock cannot determine which method to
+ * expect since there are two methods with the same name
+ * and the same number of arguments but one is using
+ * wrapper types.
+ */
+ throwExceptionWhenMultipleConstructorMatchesFound(new Constructor<?>[]{potentialConstructor,
+ constructor});
+ }
+ }
+ } else if (isPotentialVarArgsConstructor(constructor, arguments)) {
+ if (potentialConstructor == null) {
+ potentialConstructor = constructor;
+ } else {
+ /*
+ * We've already found a constructor match before, this
+ * means that PowerMock cannot determine which method to
+ * expect since there are two methods with the same name and
+ * the same number of arguments but one is using wrapper
+ * types.
+ */
+ throwExceptionWhenMultipleConstructorMatchesFound(new Constructor<?>[]{potentialConstructor,
+ constructor});
+ }
+ break;
+ } else if (arguments != null && (paramTypes.length != arguments.length)) {
+ continue;
+ }
+ }
+
+ WhiteboxImpl.throwExceptionIfConstructorWasNotFound(type, potentialConstructor, arguments);
+ return potentialConstructor;
+ }
+
+ /**
+ * Convert argument types to primitive.
+ *
+ * @param paramTypes the param types
+ * @param arguments the arguments
+ * @return the class[]
+ */
+ private static Class<?>[] convertArgumentTypesToPrimitive(Class<?>[] paramTypes, Object[] arguments) {
+ Class<?>[] types = new Class<?>[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ Class<?> argumentType = null;
+ if (arguments[i] == null) {
+ argumentType = paramTypes[i];
+ } else {
+ argumentType = getType(arguments[i]);
+ }
+ Class<?> primitiveWrapperType = PrimitiveWrapper.getPrimitiveFromWrapperType(argumentType);
+ if (primitiveWrapperType == null) {
+ types[i] = argumentType;
+ } else {
+ types[i] = primitiveWrapperType;
+ }
+ }
+ return types;
+ }
+
+ /**
+ * Throw exception if method was not found.
+ *
+ * @param type the type
+ * @param methodName the method name
+ * @param methodToMock the method to mock
+ * @param arguments the arguments
+ */
+ public static void throwExceptionIfMethodWasNotFound(Class<?> type, String methodName, Method methodToMock,
+ Object... arguments) {
+ if (methodToMock == null) {
+ String methodNameData = "";
+ if (methodName != null) {
+ methodNameData = "with name '" + methodName + "' ";
+ }
+ throw new MethodNotFoundException("No method found " + methodNameData + "with parameter types: [ "
+ + getArgumentTypesAsString(arguments) + " ] in class " + getUnmockedType(type)
+ .getName() + ".");
+ }
+ }
+
+ /**
+ * Throw exception if field was not found.
+ *
+ * @param type the type
+ * @param fieldName the field name
+ * @param field the field
+ */
+ public static void throwExceptionIfFieldWasNotFound(Class<?> type, String fieldName, Field field) {
+ if (field == null) {
+ throw new FieldNotFoundException("No field was found with name '" + fieldName + "' in class "
+ + getUnmockedType(type).getName() + ".");
+ }
+ }
+
+ /**
+ * Throw exception if constructor was not found.
+ *
+ * @param type the type
+ * @param potentialConstructor the potential constructor
+ * @param arguments the arguments
+ */
+ static void throwExceptionIfConstructorWasNotFound(Class<?> type, Constructor<?> potentialConstructor,
+ Object... arguments) {
+ if (potentialConstructor == null) {
+ String message = "No constructor found in class '" + getUnmockedType(type).getName() + "' with "
+ + "parameter types: [ " + getArgumentTypesAsString(arguments) + " ].";
+ throw new ConstructorNotFoundException(message);
+ }
+ }
+
+ /**
+ * Gets the argument types as string.
+ *
+ * @param arguments the arguments
+ * @return the argument types as string
+ */
+ private static String getArgumentTypesAsString(Object... arguments) {
+ StringBuilder argumentsAsString = new StringBuilder();
+ final String noParameters = "<none>";
+ if (arguments != null && arguments.length != 0) {
+ for (int i = 0; i < arguments.length; i++) {
+ String argumentName = null;
+ Object argument = arguments[i];
+
+ if (argument instanceof Class<?>) {
+ argumentName = ((Class<?>) argument).getName();
+ } else if (argument instanceof Class<?>[] && arguments.length == 1) {
+ Class<?>[] argumentArray = (Class<?>[]) argument;
+ if (argumentArray.length > 0) {
+ for (int j = 0; j < argumentArray.length; j++) {
+ appendArgument(argumentsAsString, j,
+ argumentArray[j] == null ? "null" : getType(argumentArray[j]).getName(),
+ argumentArray);
+ }
+ return argumentsAsString.toString();
+ } else {
+ argumentName = noParameters;
+ }
+ } else if (argument == null) {
+ argumentName = "null";
+ } else {
+ argumentName = getType(argument).getName();
+ }
+ appendArgument(argumentsAsString, i, argumentName, arguments);
+ }
+ } else {
+ argumentsAsString.append("<none>");
+ }
+ return argumentsAsString.toString();
+ }
+
+ /**
+ * Append argument.
+ *
+ * @param argumentsAsString the arguments as string
+ * @param index the index
+ * @param argumentName the argument name
+ * @param arguments the arguments
+ */
+ private static void appendArgument(StringBuilder argumentsAsString, int index, String argumentName,
+ Object[] arguments) {
+ argumentsAsString.append(argumentName);
+ if (index != arguments.length - 1) {
+ argumentsAsString.append(", ");
+ }
+ }
+
+ /**
+ * Invoke a constructor. Useful for testing classes with a private
+ * constructor when PowerMock cannot determine which constructor to invoke.
+ * This only happens if you have two constructors with the same number of
+ * arguments where one is using primitive data types and the other is using
+ * the wrapped counter part. For example:
+ * <p/>
+ * <pre>
+ * public class MyClass {
+ * private MyClass(Integer i) {
+ * ...
+ * }
+ *
+ * private MyClass(int i) {
+ * ...
+ * }
+ * </pre>
+ * <p/>
+ * This ought to be a really rare case. So for most situation, use
+ *
+ * @param <T> the generic type
+ * @param classThatContainsTheConstructorToTest the class that contains the constructor to test
+ * @param parameterTypes the parameter types
+ * @param arguments the arguments
+ * @return The object created after the constructor has been invoked.
+ * @throws Exception If an exception occur when invoking the constructor.
+ * {@link #invokeConstructor(Class, Object...)} instead.
+ */
+ public static <T> T invokeConstructor(Class<T> classThatContainsTheConstructorToTest, Class<?>[] parameterTypes,
+ Object[] arguments) throws Exception {
+ if (parameterTypes != null && arguments != null) {
+ if (parameterTypes.length != arguments.length) {
+ throw new IllegalArgumentException("parameterTypes and arguments must have the same length");
+ }
+ }
+
+ Constructor<T> constructor = null;
+ try {
+ constructor = classThatContainsTheConstructorToTest.getDeclaredConstructor(parameterTypes);
+ } catch (Exception e) {
+ throw new ConstructorNotFoundException("Could not lookup the constructor", e);
+ }
+
+ return createInstance(constructor, arguments);
+ }
+
+ /**
+ * Invoke a constructor. Useful for testing classes with a private
+ * constructor.
+ *
+ * @param <T> the generic type
+ * @param classThatContainsTheConstructorToTest the class that contains the constructor to test
+ * @param arguments the arguments
+ * @return The object created after the constructor has been invoked.
+ * @throws Exception If an exception occur when invoking the constructor.
+ */
+ public static <T> T invokeConstructor(Class<T> classThatContainsTheConstructorToTest, Object... arguments)
+ throws Exception {
+
+ if (classThatContainsTheConstructorToTest == null) {
+ throw new IllegalArgumentException("The class should contain the constructor cannot be null.");
+ }
+
+ Class<?>[] argumentTypes = null;
+ if (arguments == null) {
+ argumentTypes = new Class<?>[0];
+ } else {
+ argumentTypes = new Class<?>[arguments.length];
+ for (int i = 0; i < arguments.length; i++) {
+ argumentTypes[i] = getType(arguments[i]);
+ }
+ }
+
+ Constructor<T> constructor = null;
+
+ constructor = getBestCandidateConstructor(classThatContainsTheConstructorToTest, argumentTypes, arguments);
+
+ return createInstance(constructor, arguments);
+ }
+
+ private static <T> Constructor<T> getBestCandidateConstructor(Class<T> classThatContainsTheConstructorToTest, Class<?>[] argumentTypes, Object[] arguments) {
+ Constructor<T> constructor;
+
+
+ Constructor<T> potentialConstructorWrapped = getPotentialConstructorWrapped(classThatContainsTheConstructorToTest, argumentTypes);
+
+ Constructor<T> potentialConstructorPrimitive = getPotentialConstructorPrimitive(classThatContainsTheConstructorToTest, argumentTypes);
+
+ if (potentialConstructorPrimitive == null && potentialConstructorWrapped == null) {
+ // Check if we can find a matching var args constructor.
+ constructor = getPotentialVarArgsConstructor(classThatContainsTheConstructorToTest, arguments);
+ if (constructor == null) {
+ throw new ConstructorNotFoundException("Failed to find a constructor with parameter types: ["
+ + getArgumentTypesAsString(arguments) + "]");
+ }
+ } else if (potentialConstructorPrimitive == null) {
+ constructor = potentialConstructorWrapped;
+ } else if (potentialConstructorWrapped == null) {
+ constructor = potentialConstructorPrimitive;
+ } else if (arguments == null || arguments.length == 0 && potentialConstructorPrimitive != null) {
+ constructor = potentialConstructorPrimitive;
+ } else {
+ throw new TooManyConstructorsFoundException(
+ "Could not determine which constructor to execute. Please specify the parameter types by hand.");
+ }
+ return constructor;
+ }
+
+ private static <T> Constructor<T> getPotentialConstructorWrapped(Class<T> classThatContainsTheConstructorToTest, Class<?>[] argumentTypes) {
+ return new CandidateConstructorSearcher<T>(classThatContainsTheConstructorToTest, argumentTypes)
+ .findConstructor();
+ }
+
+ private static <T> Constructor<T> getPotentialConstructorPrimitive(Class<T> classThatContainsTheConstructorToTest, Class<?>[] argumentTypes) {
+
+ Constructor<T> potentialConstructorPrimitive = null;
+ try {
+ Class<?>[] primitiveType = PrimitiveWrapper.toPrimitiveType(argumentTypes);
+
+ if (!argumentTypesEqualsPrimitiveTypes(argumentTypes, primitiveType)) {
+
+ potentialConstructorPrimitive = new CandidateConstructorSearcher<T>(classThatContainsTheConstructorToTest, primitiveType)
+ .findConstructor();
+ }
+ } catch (Exception e) {
+ // Do nothing
+ }
+ return potentialConstructorPrimitive;
+ }
+
+ private static boolean argumentTypesEqualsPrimitiveTypes(Class<?>[] argumentTypes, Class<?>[] primitiveType) {
+ for (int index = 0; index < argumentTypes.length; index++) {
+ if (!argumentTypes[index].equals(primitiveType[index])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Gets the potential var args constructor.
+ *
+ * @param <T> the generic type
+ * @param classThatContainsTheConstructorToTest the class that contains the constructor to test
+ * @param arguments the arguments
+ * @return the potential var args constructor
+ */
+ @SuppressWarnings("unchecked")
+ private static <T> Constructor<T> getPotentialVarArgsConstructor(Class<T> classThatContainsTheConstructorToTest,
+ Object... arguments) {
+ Constructor<T>[] declaredConstructors = (Constructor<T>[]) classThatContainsTheConstructorToTest
+ .getDeclaredConstructors();
+ for (Constructor<T> possibleVarArgsConstructor : declaredConstructors) {
+ if (possibleVarArgsConstructor.isVarArgs()) {
+ if (arguments == null || arguments.length == 0) {
+ return possibleVarArgsConstructor;
+ } else {
+ Class<?>[] parameterTypes = possibleVarArgsConstructor.getParameterTypes();
+ if (parameterTypes[parameterTypes.length - 1].getComponentType().isAssignableFrom(
+ getType(arguments[0]))) {
+ return possibleVarArgsConstructor;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates the instance.
+ *
+ * @param <T> the generic type
+ * @param constructor the constructor
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ */
+ private static <T> T createInstance(Constructor<T> constructor, Object... arguments) throws Exception {
+ if (constructor == null) {
+ throw new IllegalArgumentException("Constructor cannot be null");
+ }
+ constructor.setAccessible(true);
+
+ T createdObject = null;
+ try {
+ if (constructor.isVarArgs()) {
+ Class<?>[] parameterTypes = constructor.getParameterTypes();
+ final int varArgsIndex = parameterTypes.length - 1;
+ Class<?> varArgsType = parameterTypes[varArgsIndex].getComponentType();
+ Object varArgsArrayInstance = createAndPopulateVarArgsArray(varArgsType, varArgsIndex, arguments);
+ Object[] completeArgumentList = new Object[parameterTypes.length];
+ System.arraycopy(arguments, 0, completeArgumentList, 0, varArgsIndex);
+ completeArgumentList[completeArgumentList.length - 1] = varArgsArrayInstance;
+ createdObject = constructor.newInstance(completeArgumentList);
+ } else {
+ createdObject = constructor.newInstance(arguments);
+ }
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ }
+ }
+ return createdObject;
+ }
+
+ /**
+ * Creates the and populate var args array.
+ *
+ * @param varArgsType the var args type
+ * @param varArgsStartPosition the var args start position
+ * @param arguments the arguments
+ * @return the object
+ */
+ private static Object createAndPopulateVarArgsArray(Class<?> varArgsType, int varArgsStartPosition,
+ Object... arguments) {
+ Object arrayInstance = Array.newInstance(varArgsType, arguments.length - varArgsStartPosition);
+ for (int i = varArgsStartPosition; i < arguments.length; i++) {
+ Array.set(arrayInstance, i - varArgsStartPosition, arguments[i]);
+ }
+ return arrayInstance;
+ }
+
+ /**
+ * Get all declared constructors in the class and set accessible to
+ * <code>true</code>.
+ *
+ * @param clazz The class whose constructors to get.
+ * @return All constructors declared in this class hierarchy.
+ */
+ public static Constructor<?>[] getAllConstructors(Class<?> clazz) {
+ Constructor<?>[] declaredConstructors = clazz.getDeclaredConstructors();
+ for (Constructor<?> constructor : declaredConstructors) {
+ if (!constructor.isAccessible()) {
+ constructor.setAccessible(true);
+ }
+ }
+ return declaredConstructors;
+ }
+
+ /**
+ * Get all methods in a class hierarchy! Both declared an non-declared (no
+ * duplicates).
+ *
+ * @param clazz The class whose methods to get.
+ * @return All methods declared in this class hierarchy.
+ */
+ public static Method[] getAllMethods(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("You must specify a class in order to get the methods.");
+ }
+ Set<Method> methods = new LinkedHashSet<Method>();
+
+ Class<?> thisType = clazz;
+
+ while (thisType != null) {
+ final Class<?> type = thisType;
+ final Method[] declaredMethods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() {
+
+ @Override
+ public Method[] run() {
+ return type.getDeclaredMethods();
+ }
+
+ });
+ for (Method method : declaredMethods) {
+ method.setAccessible(true);
+ methods.add(method);
+ }
+ Collections.addAll(methods, type.getMethods());
+ thisType = thisType.getSuperclass();
+ }
+ return methods.toArray(new Method[methods.size()]);
+ }
+
+ /**
+ * Get all public methods for a class (no duplicates)! Note that the
+ * class-hierarchy will not be traversed.
+ *
+ * @param clazz The class whose methods to get.
+ * @return All public methods declared in class.
+ */
+ private static Method[] getAllPublicMethods(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("You must specify a class in order to get the methods.");
+ }
+ Set<Method> methods = new LinkedHashSet<Method>();
+
+ for (Method method : clazz.getMethods()) {
+ method.setAccessible(true);
+ methods.add(method);
+ }
+ return methods.toArray(new Method[0]);
+ }
+
+ /**
+ * Get all fields in a class hierarchy! Both declared an non-declared (no
+ * duplicates).
+ *
+ * @param clazz The class whose fields to get.
+ * @return All fields declared in this class hierarchy.
+ */
+ public static Field[] getAllFields(Class<?> clazz) {
+ if (clazz == null) {
+ throw new IllegalArgumentException("You must specify the class that contains the fields");
+ }
+ Set<Field> fields = new LinkedHashSet<Field>();
+
+ Class<?> thisType = clazz;
+
+ while (thisType != null) {
+ final Field[] declaredFields = thisType.getDeclaredFields();
+ for (Field field : declaredFields) {
+ field.setAccessible(true);
+ fields.add(field);
+ }
+ thisType = thisType.getSuperclass();
+ }
+ return fields.toArray(new Field[fields.size()]);
+ }
+
+ /**
+ * Get the first parent constructor defined in a super class of
+ * <code>klass</code>.
+ *
+ * @param klass The class where the constructor is located. <code>null</code>
+ * ).
+ * @return A .
+ */
+ public static Constructor<?> getFirstParentConstructor(Class<?> klass) {
+ try {
+ return getUnmockedType(klass).getSuperclass().getDeclaredConstructors()[0];
+ } catch (Exception e) {
+ throw new ConstructorNotFoundException("Failed to lookup constructor.", e);
+ }
+ }
+
+ /**
+ * Finds and returns a method based on the input parameters. If no
+ * <code>parameterTypes</code> are present the method will return the first
+ * method with name <code>methodNameToMock</code>. If no method was found,
+ * <code>null</code> will be returned. If no <code>methodName</code> is
+ * specified the method will be found based on the parameter types. If
+ * neither method name nor parameters are specified an
+ *
+ * @param <T> the generic type
+ * @param type the type
+ * @param methodName the method name
+ * @param parameterTypes the parameter types
+ * @return the method {@link IllegalArgumentException} will be thrown.
+ */
+ public static <T> Method findMethod(Class<T> type, String methodName, Class<?>... parameterTypes) {
+ if (methodName == null && parameterTypes == null) {
+ throw new IllegalArgumentException("You must specify a method name or parameter types.");
+ }
+ List<Method> matchingMethodsList = new LinkedList<Method>();
+ for (Method method : getAllMethods(type)) {
+ if (methodName == null || method.getName().equals(methodName)) {
+ if (parameterTypes != null && parameterTypes.length > 0) {
+ // If argument types was supplied, make sure that they
+ // match.
+ Class<?>[] paramTypes = method.getParameterTypes();
+ if (!checkIfParameterTypesAreSame(method.isVarArgs(), parameterTypes, paramTypes)) {
+ continue;
+ }
+ }
+ // Add the method to the matching methods list.
+ matchingMethodsList.add(method);
+ }
+ }
+
+ Method methodToMock = null;
+ if (matchingMethodsList.size() > 0) {
+ if (matchingMethodsList.size() == 1) {
+ // We've found a unique method match.
+ methodToMock = matchingMethodsList.get(0);
+ } else if ((parameterTypes != null ? parameterTypes.length : 0) == 0) {
+ /*
+ * If we've found several matches and we've supplied no
+ * parameter types, go through the list of found methods and see
+ * if we have a method with no parameters. In that case return
+ * that method.
+ */
+ for (Method method : matchingMethodsList) {
+ if (method.getParameterTypes().length == 0) {
+ methodToMock = method;
+ break;
+ }
+ }
+
+ if (methodToMock == null) {
+ WhiteboxImpl.throwExceptionWhenMultipleMethodMatchesFound("argument parameter types",
+ matchingMethodsList.toArray(new Method[matchingMethodsList.size()]));
+ }
+ } else {
+ // We've found several matching methods.
+ WhiteboxImpl.throwExceptionWhenMultipleMethodMatchesFound("argument parameter types",
+ matchingMethodsList.toArray(new Method[matchingMethodsList.size()]));
+ }
+ }
+
+ return methodToMock;
+ }
+
+ /**
+ * Checks if is proxy.
+ *
+ * @param type the type
+ * @return true, if is proxy
+ */
+ public static boolean isProxy(Class<?> type) {
+ return proxyFramework.isProxy(type);
+ }
+
+ /**
+ * Gets the unmocked type.
+ *
+ * @param <T> the generic type
+ * @param type the type
+ * @return the unmocked type
+ */
+ public static <T> Class<?> getUnmockedType(Class<T> type) {
+ if (type == null) {
+ throw new IllegalArgumentException("type cannot be null");
+ }
+
+ Class<?> unmockedType = null;
+ if (proxyFramework != null && proxyFramework.isProxy(type)) {
+ unmockedType = proxyFramework.getUnproxiedType(type);
+ } else if (Proxy.isProxyClass(type)) {
+ unmockedType = type.getInterfaces()[0];
+ } else {
+ unmockedType = type;
+ }
+ return unmockedType;
+ }
+
+ /**
+ * Throw exception when multiple method matches found.
+ *
+ * @param helpInfo the help info
+ * @param methods the methods
+ */
+ static void throwExceptionWhenMultipleMethodMatchesFound(String helpInfo, Method[] methods) {
+ if (methods == null || methods.length < 2) {
+ throw new IllegalArgumentException(
+ "Internal error: throwExceptionWhenMultipleMethodMatchesFound needs at least two methods.");
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("Several matching methods found, please specify the ");
+ sb.append(helpInfo);
+ sb.append(" so that PowerMock can determine which method you're referring to.\n");
+ sb.append("Matching methods in class ").append(methods[0].getDeclaringClass().getName()).append(" were:\n");
+
+ for (Method method : methods) {
+ sb.append(method.getReturnType().getName()).append(" ");
+ sb.append(method.getName()).append("( ");
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ for (Class<?> paramType : parameterTypes) {
+ sb.append(paramType.getName()).append(".class ");
+ }
+ sb.append(")\n");
+ }
+ throw new TooManyMethodsFoundException(sb.toString());
+ }
+
+ /**
+ * Throw exception when multiple constructor matches found.
+ *
+ * @param constructors the constructors
+ */
+ static void throwExceptionWhenMultipleConstructorMatchesFound(Constructor<?>[] constructors) {
+ if (constructors == null || constructors.length < 2) {
+ throw new IllegalArgumentException(
+ "Internal error: throwExceptionWhenMultipleConstructorMatchesFound needs at least two constructors.");
+ }
+ StringBuilder sb = new StringBuilder();
+ sb.append("Several matching constructors found, please specify the argument parameter types so that PowerMock can determine which method you're referring to.\n");
+ sb.append("Matching constructors in class ").append(constructors[0].getDeclaringClass().getName())
+ .append(" were:\n");
+
+ for (Constructor<?> constructor : constructors) {
+ sb.append(constructor.getName()).append("( ");
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ for (Class<?> paramType : parameterTypes) {
+ sb.append(paramType.getName()).append(".class ");
+ }
+ sb.append(")\n");
+ }
+ throw new TooManyConstructorsFoundException(sb.toString());
+ }
+
+ /**
+ * Find method or throw exception.
+ *
+ * @param type the type
+ * @param methodName the method name
+ * @param parameterTypes the parameter types
+ * @return the method
+ */
+ @SuppressWarnings("all")
+ public static Method findMethodOrThrowException(Class<?> type, String methodName, Class<?>... parameterTypes) {
+ Method methodToMock = findMethod(type, methodName, parameterTypes);
+ throwExceptionIfMethodWasNotFound(type, methodName, methodToMock, parameterTypes);
+ return methodToMock;
+ }
+
+ /**
+ * Get an array of {@link Method}'s that matches the supplied list of method
+ * names. Both instance and static methods are taken into account.
+ *
+ * @param clazz The class that should contain the methods.
+ * @param methodNames Names of the methods that will be returned.
+ * @return An array of Method's.
+ */
+ public static Method[] getMethods(Class<?> clazz, String... methodNames) {
+ if (methodNames == null || methodNames.length == 0) {
+ throw new IllegalArgumentException("You must supply at least one method name.");
+ }
+ final List<Method> methodsToMock = new LinkedList<Method>();
+ Method[] allMethods = null;
+ if (clazz.isInterface()) {
+ allMethods = getAllPublicMethods(clazz);
+ } else {
+ allMethods = getAllMethods(clazz);
+ }
+
+ for (Method method : allMethods) {
+ for (String methodName : methodNames) {
+ if (method.getName().equals(methodName)) {
+ method.setAccessible(true);
+ methodsToMock.add(method);
+ }
+ }
+ }
+
+ final Method[] methodArray = methodsToMock.toArray(new Method[0]);
+ if (methodArray.length == 0) {
+ throw new MethodNotFoundException(String.format(
+ "No methods matching the name(s) %s were found in the class hierarchy of %s.",
+ concatenateStrings(methodNames), getType(clazz)));
+ }
+ return methodArray;
+ }
+
+ /**
+ * Get an array of {@link Method}'s that matches the method name and whose
+ * argument types are assignable from <code>expectedTypes</code>. Both
+ * instance and static methods are taken into account.
+ *
+ * @param clazz The class that should contain the methods.
+ * @param methodName Names of the methods that will be returned.
+ * @param expectedTypes The methods must match
+ * @param exactParameterTypeMatch <code>true</code> if the <code>expectedTypes</code> must match
+ * the parameter types must match exactly, <code>false</code> if
+ * the <code>expectedTypes</code> are allowed to be converted
+ * into primitive types if they are of a wrapped type and still
+ * match.
+ * @return An array of Method's.
+ */
+ public static Method[] getMethods(Class<?> clazz, String methodName, Class<?>[] expectedTypes,
+ boolean exactParameterTypeMatch) {
+ List<Method> matchingArgumentTypes = new LinkedList<Method>();
+ Method[] methods = getMethods(clazz, methodName);
+ for (Method method : methods) {
+ final Class<?>[] parameterTypes = method.getParameterTypes();
+ if (checkIfParameterTypesAreSame(method.isVarArgs(), expectedTypes, parameterTypes)
+ || (!exactParameterTypeMatch && checkIfParameterTypesAreSame(method.isVarArgs(),
+ convertParameterTypesToPrimitive(expectedTypes), parameterTypes))) {
+ matchingArgumentTypes.add(method);
+ }
+ }
+ final Method[] methodArray = matchingArgumentTypes.toArray(new Method[0]);
+ if (methodArray.length == 0) {
+ throw new MethodNotFoundException(String.format(
+ "No methods matching the name(s) %s were found in the class hierarchy of %s.",
+ concatenateStrings(methodName), getType(clazz)));
+ }
+ return matchingArgumentTypes.toArray(new Method[matchingArgumentTypes.size()]);
+ }
+
+ /**
+ * Get an array of {@link Field}'s that matches the supplied list of field
+ * names. Both instance and static fields are taken into account.
+ *
+ * @param clazz The class that should contain the fields.
+ * @param fieldNames Names of the fields that will be returned.
+ * @return An array of Field's. May be of length 0 but not .
+ */
+ public static Field[] getFields(Class<?> clazz, String... fieldNames) {
+ final List<Field> fields = new LinkedList<Field>();
+
+ for (Field field : getAllFields(clazz)) {
+ for (String fieldName : fieldNames) {
+ if (field.getName().equals(fieldName)) {
+ fields.add(field);
+ }
+ }
+ }
+
+ final Field[] fieldArray = fields.toArray(new Field[fields.size()]);
+ if (fieldArray.length == 0) {
+ throw new FieldNotFoundException(String.format(
+ "No fields matching the name(s) %s were found in the class hierarchy of %s.",
+ concatenateStrings(fieldNames), getType(clazz)));
+ }
+ return fieldArray;
+ }
+
+ /**
+ * Perform method invocation.
+ *
+ * @param <T> the generic type
+ * @param tested the tested
+ * @param methodToInvoke the method to invoke
+ * @param arguments the arguments
+ * @return the t
+ * @throws Exception the exception
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T performMethodInvocation(Object tested, Method methodToInvoke, Object... arguments)
+ throws Exception {
+ final boolean accessible = methodToInvoke.isAccessible();
+ if (!accessible) {
+ methodToInvoke.setAccessible(true);
+ }
+ try {
+ if (isPotentialVarArgsMethod(methodToInvoke, arguments)) {
+ Class<?>[] parameterTypes = methodToInvoke.getParameterTypes();
+ final int varArgsIndex = parameterTypes.length - 1;
+ Class<?> varArgsType = parameterTypes[varArgsIndex].getComponentType();
+ Object varArgsArrayInstance = createAndPopulateVarArgsArray(varArgsType, varArgsIndex, arguments);
+ Object[] completeArgumentList = new Object[parameterTypes.length];
+ System.arraycopy(arguments, 0, completeArgumentList, 0, varArgsIndex);
+ completeArgumentList[completeArgumentList.length - 1] = varArgsArrayInstance;
+ return (T) methodToInvoke.invoke(tested, completeArgumentList);
+ } else {
+ return (T) methodToInvoke.invoke(tested, arguments == null ? new Object[]{arguments} : arguments);
+ }
+ } catch (InvocationTargetException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof Exception) {
+ throw (Exception) cause;
+ } else if (cause instanceof Error) {
+ throw (Error) cause;
+ } else {
+ throw new MethodInvocationException(cause);
+ }
+ } finally {
+ if (!accessible) {
+ methodToInvoke.setAccessible(false);
+ }
+ }
+ }
+
+ /**
+ * Gets the all method except.
+ *
+ * @param <T> the generic type
+ * @param type the type
+ * @param methodNames the method names
+ * @return the all method except
+ */
+ public static <T> Method[] getAllMethodExcept(Class<T> type, String... methodNames) {
+ List<Method> methodsToMock = new LinkedList<Method>();
+ Method[] methods = getAllMethods(type);
+ iterateMethods:
+ for (Method method : methods) {
+ for (String methodName : methodNames) {
+ if (method.getName().equals(methodName)) {
+ continue iterateMethods;
+ }
+ }
+ methodsToMock.add(method);
+ }
+ return methodsToMock.toArray(new Method[0]);
+ }
+
+ /**
+ * Gets the all metods except.
+ *
+ * @param <T> the generic type
+ * @param type the type
+ * @param methodNameToExclude the method name to exclude
+ * @param argumentTypes the argument types
+ * @return the all metods except
+ */
+ public static <T> Method[] getAllMetodsExcept(Class<T> type, String methodNameToExclude, Class<?>[] argumentTypes) {
+ Method[] methods = getAllMethods(type);
+ List<Method> methodList = new ArrayList<Method>();
+ outer:
+ for (Method method : methods) {
+ if (method.getName().equals(methodNameToExclude)) {
+ if (argumentTypes != null && argumentTypes.length > 0) {
+ final Class<?>[] args = method.getParameterTypes();
+ if (args != null && args.length == argumentTypes.length) {
+ for (int i = 0; i < args.length; i++) {
+ if (args[i].isAssignableFrom(getUnmockedType(argumentTypes[i]))) {
+ /*
+ * Method was not found thus it should not be
+ * mocked. Continue to investigate the next
+ * method.
+ */
+ continue outer;
+ }
+ }
+ }
+ } else {
+ continue;
+ }
+ }
+ methodList.add(method);
+ }
+ return methodList.toArray(new Method[0]);
+ }
+
+ /**
+ * Are all methods static.
+ *
+ * @param methods the methods
+ * @return true, if successful
+ */
+ public static boolean areAllMethodsStatic(Method... methods) {
+ for (Method method : methods) {
+ if (!Modifier.isStatic(method.getModifiers())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Check if all arguments are of the same type.
+ *
+ * @param arguments the arguments
+ * @return true, if successful
+ */
+ static boolean areAllArgumentsOfSameType(Object[] arguments) {
+ if (arguments == null || arguments.length <= 1) {
+ return true;
+ }
+
+ // Handle null values
+ int index = 0;
+ Object object = null;
+ while (object == null && index < arguments.length) {
+ object = arguments[index++];
+ }
+
+ if (object == null) {
+ return true;
+ }
+ // End of handling null values
+
+ final Class<?> firstArgumentType = getType(object);
+ for (int i = index; i < arguments.length; i++) {
+ final Object argument = arguments[i];
+ if (argument != null && !getType(argument).isAssignableFrom(firstArgumentType)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check argument types match parameter types.
+ *
+ * @param isVarArgs If the last parameter is a var args.
+ * @param parameterTypes the parameter types
+ * @param arguments the arguments
+ * @return if all actual parameter types are assignable from the expected
+ * arguments, otherwise.
+ */
+ private static boolean checkArgumentTypesMatchParameterTypes(boolean isVarArgs, Class<?>[] parameterTypes,
+ Object[] arguments) {
+ if (parameterTypes == null) {
+ throw new IllegalArgumentException("parameter types cannot be null");
+ } else if (!isVarArgs && arguments.length != parameterTypes.length) {
+ return false;
+ }
+ for (int i = 0; i < arguments.length; i++) {
+ Object argument = arguments[i];
+ if (argument == null) {
+ final int index;
+ if (i >= parameterTypes.length) {
+ index = parameterTypes.length - 1;
+ } else {
+ index = i;
+ }
+ final Class<?> type = parameterTypes[index];
+ if (type.isPrimitive()) {
+ // Primitives cannot be null
+ return false;
+ } else {
+ continue;
+ }
+ } else if (i >= parameterTypes.length) {
+ if (isAssignableFrom(parameterTypes[parameterTypes.length - 1], getType(argument))) {
+ continue;
+ } else {
+ return false;
+ }
+ } else {
+ boolean assignableFrom = isAssignableFrom(parameterTypes[i], getType(argument));
+ final boolean isClass = parameterTypes[i].equals(Class.class) && isClass(argument);
+ if (!assignableFrom && !isClass) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ private static boolean isAssignableFrom(Class<?> type, Class<?> from) {
+ boolean assignableFrom;
+ Class<?> theType = getComponentType(type);
+ Class<?> theFrom = getComponentType(from);
+ assignableFrom = theType.isAssignableFrom(theFrom);
+ if (!assignableFrom && PrimitiveWrapper.hasPrimitiveCounterPart(theFrom)) {
+ final Class<?> primitiveFromWrapperType = PrimitiveWrapper.getPrimitiveFromWrapperType(theFrom);
+ if (primitiveFromWrapperType != null) {
+ assignableFrom = theType.isAssignableFrom(primitiveFromWrapperType);
+ }
+ }
+ return assignableFrom;
+ }
+
+ private static Class<?> getComponentType(Class<?> type) {
+ Class<?> theType = type;
+ while (theType.isArray()) {
+ theType = theType.getComponentType();
+ }
+ return theType;
+ }
+
+ /**
+ * Gets the type.
+ *
+ * @param object the object
+ * @return The type of the of an object.
+ */
+ public static Class<?> getType(Object object) {
+ Class<?> type = null;
+ if (isClass(object)) {
+ type = (Class<?>) object;
+ } else if (object != null) {
+ type = object.getClass();
+ }
+ return type == null ? null : getUnmockedType(type);
+ }
+
+ /**
+ * Get an inner class type.
+ *
+ * @param declaringClass The class in which the inner class is declared.
+ * @param name The unqualified name (simple name) of the inner class.
+ * @return The type.
+ * @throws ClassNotFoundException the class not found exception
+ */
+ @SuppressWarnings("unchecked")
+ public static Class<Object> getInnerClassType(Class<?> declaringClass, String name) throws ClassNotFoundException {
+ return (Class<Object>) Class.forName(declaringClass.getName() + "$" + name);
+ }
+
+ /**
+ * Get the type of a local inner class.
+ *
+ * @param declaringClass The class in which the local inner class is declared.
+ * @param occurrence The occurrence of the local class. For example if you have two
+ * local classes in the <code>declaringClass</code> you must pass
+ * in <code>1</code> if you want to get the type for the first
+ * one or <code>2</code> if you want the second one.
+ * @param name The unqualified name (simple name) of the local class.
+ * @return The type.
+ * @throws ClassNotFoundException the class not found exception
+ */
+ @SuppressWarnings("unchecked")
+ public static Class<Object> getLocalClassType(Class<?> declaringClass, int occurrence, String name)
+ throws ClassNotFoundException {
+ return (Class<Object>) Class.forName(declaringClass.getName() + "$" + occurrence + name);
+ }
+
+ /**
+ * Get the type of an anonymous inner class.
+ *
+ * @param declaringClass The class in which the anonymous inner class is declared.
+ * @param occurrence The occurrence of the anonymous inner class. For example if
+ * you have two anonymous inner classes classes in the
+ * <code>declaringClass</code> you must pass in <code>1</code> if
+ * you want to get the type for the first one or <code>2</code>
+ * if you want the second one.
+ * @return The type.
+ * @throws ClassNotFoundException the class not found exception
+ */
+ @SuppressWarnings("unchecked")
+ public static Class<Object> getAnonymousInnerClassType(Class<?> declaringClass, int occurrence)
+ throws ClassNotFoundException {
+ return (Class<Object>) Class.forName(declaringClass.getName() + "$" + occurrence);
+ }
+
+ /**
+ * Get all fields annotated with a particular annotation. This method
+ * traverses the class hierarchy when checking for the annotation.
+ *
+ * @param object The object to look for annotations. Note that if're you're
+ * passing an object only instance fields are checked, passing a
+ * class will only check static fields.
+ * @param annotation The annotation type to look for.
+ * @param additionalAnnotations Optionally more annotations to look for. If any of the
+ * annotations are associated with a particular field it will be
+ * added to the resulting <code>Set</code>.
+ * @return A set of all fields containing the particular annotation.
+ */
+ @SuppressWarnings("unchecked")
+ public static Set<Field> getFieldsAnnotatedWith(Object object, Class<? extends Annotation> annotation,
+ Class<? extends Annotation>... additionalAnnotations) {
+ Class<? extends Annotation>[] annotations = null;
+ if (additionalAnnotations == null || additionalAnnotations.length == 0) {
+ annotations = (Class<? extends Annotation>[]) new Class<?>[]{annotation};
+ } else {
+ annotations = (Class<? extends Annotation>[]) new Class<?>[additionalAnnotations.length + 1];
+ annotations[0] = annotation;
+ System.arraycopy(additionalAnnotations, 0, annotations, 1, additionalAnnotations.length);
+ }
+ return getFieldsAnnotatedWith(object, annotations);
+ }
+
+ /**
+ * Get all fields annotated with a particular annotation. This method
+ * traverses the class hierarchy when checking for the annotation.
+ *
+ * @param object The object to look for annotations. Note that if're you're
+ * passing an object only instance fields are checked, passing a
+ * class will only check static fields.
+ * @param annotationTypes The annotation types to look for
+ * @return A set of all fields containing the particular annotation(s).
+ * @since 1.3
+ */
+ public static Set<Field> getFieldsAnnotatedWith(Object object, Class<? extends Annotation>[] annotationTypes) {
+ return findAllFieldsUsingStrategy(new FieldAnnotationMatcherStrategy(annotationTypes), object, true,
+ getType(object));
+ }
+
+ /**
+ * Get all fields assignable from a particular type. This method traverses
+ * the class hierarchy when checking for the type.
+ *
+ * @param object The object to look for type. Note that if're you're passing an
+ * object only instance fields are checked, passing a class will
+ * only check static fields.
+ * @param type The type to look for.
+ * @return A set of all fields of the particular type.
+ */
+ public static Set<Field> getFieldsOfType(Object object, Class<?> type) {
+ return findAllFieldsUsingStrategy(new AssignableFromFieldTypeMatcherStrategy(type), object, true,
+ getType(object));
+ }
+
+ /**
+ * Get all instance fields for a particular object. It returns all fields
+ * regardless of the field modifier and regardless of where in the class
+ * hierarchy a field is located.
+ *
+ * @param object The object whose instance fields to get.
+ * @return All instance fields in the hierarchy. All fields are set to
+ * accessible
+ */
+ public static Set<Field> getAllInstanceFields(Object object) {
+ return findAllFieldsUsingStrategy(new AllFieldsMatcherStrategy(), object, true, getType(object));
+ }
+
+ /**
+ * Get all static fields for a particular type.
+ *
+ * @param type The class whose static fields to get.
+ * @return All static fields in . All fields are set to accessible.
+ */
+ public static Set<Field> getAllStaticFields(Class<?> type) {
+ final Set<Field> fields = new LinkedHashSet<Field>();
+ final Field[] declaredFields = type.getDeclaredFields();
+ for (Field field : declaredFields) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ field.setAccessible(true);
+ fields.add(field);
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * Checks if is class.
+ *
+ * @param argument the argument
+ * @return true, if is class
+ */
+ public static boolean isClass(Object argument) {
+ return argument instanceof Class<?>;
+ }
+
+ /**
+ * Check if parameter types are same.
+ *
+ * @param isVarArgs Whether or not the method or constructor contains var args.
+ * @param expectedParameterTypes the expected parameter types
+ * @param actualParameterTypes the actual parameter types
+ * @return if all actual parameter types are assignable from the expected
+ * parameter types, otherwise.
+ */
+ public static boolean checkIfParameterTypesAreSame(boolean isVarArgs, Class<?>[] expectedParameterTypes,
+ Class<?>[] actualParameterTypes) {
+ return new ParameterTypesMatcher(isVarArgs, expectedParameterTypes, actualParameterTypes).match();
+ }
+
+ /**
+ * Gets the field.
+ *
+ * @param fieldName the field name
+ * @param where the where
+ * @return the field
+ */
+ private static Field getField(String fieldName, Class<?> where) {
+ if (where == null) {
+ throw new IllegalArgumentException("where cannot be null");
+ }
+
+ Field field = null;
+ try {
+ field = where.getDeclaredField(fieldName);
+ field.setAccessible(true);
+ } catch (NoSuchFieldException e) {
+ throw new FieldNotFoundException("Field '" + fieldName + "' was not found in class " + where.getName()
+ + ".");
+ }
+ return field;
+ }
+
+ /**
+ * Find field or throw exception.
+ *
+ * @param fieldType the field type
+ * @param where the where
+ * @return the field
+ */
+ private static Field findFieldOrThrowException(Class<?> fieldType, Class<?> where) {
+ if (fieldType == null || where == null) {
+ throw new IllegalArgumentException("fieldType and where cannot be null");
+ }
+ Field field = null;
+ for (Field currentField : where.getDeclaredFields()) {
+ currentField.setAccessible(true);
+ if (currentField.getType().equals(fieldType)) {
+ field = currentField;
+ break;
+ }
+ }
+ if (field == null) {
+ throw new FieldNotFoundException("Cannot find a field of type " + fieldType + "in where.");
+ }
+ return field;
+ }
+
+ /**
+ * Sets the field.
+ *
+ * @param object the object
+ * @param value the value
+ * @param foundField the found field
+ */
+ private static void setField(Object object, Object value, Field foundField) {
+ foundField.setAccessible(true);
+ try {
+ foundField.set(object, value);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Internal error: Failed to set field in method setInternalState.", e);
+ }
+ }
+
+ /**
+ * Concatenate strings.
+ *
+ * @param stringsToConcatenate the strings to concatenate
+ * @return the string
+ */
+ private static String concatenateStrings(String... stringsToConcatenate) {
+ StringBuilder builder = new StringBuilder();
+ final int stringsLength = stringsToConcatenate.length;
+ for (int i = 0; i < stringsLength; i++) {
+ if (i == stringsLength - 1 && stringsLength != 1) {
+ builder.append(" or ");
+ } else if (i != 0) {
+ builder.append(", ");
+ }
+ builder.append(stringsToConcatenate[i]);
+ }
+ return builder.toString();
+ }
+
+ /**
+ * Checks if is potential var args method.
+ *
+ * @param method the method
+ * @param arguments the arguments
+ * @return true, if is potential var args method
+ */
+ private static boolean isPotentialVarArgsMethod(Method method, Object[] arguments) {
+ return doesParameterTypesMatchForVarArgsInvocation(method.isVarArgs(), method.getParameterTypes(), arguments);
+ }
+
+ /**
+ * Checks if is potential var args constructor.
+ *
+ * @param constructor the constructor
+ * @param arguments the arguments
+ * @return true, if is potential var args constructor
+ */
+ private static boolean isPotentialVarArgsConstructor(Constructor<?> constructor, Object[] arguments) {
+ final Class<?>[] parameterTypes = constructor.getParameterTypes();
+ return doesParameterTypesMatchForVarArgsInvocation(constructor.isVarArgs(), parameterTypes, arguments);
+ }
+
+ /**
+ * Does parameter types match for var args invocation.
+ *
+ * @param isVarArgs the is var args
+ * @param parameterTypes the parameter types
+ * @param arguments the arguments
+ * @return true, if successful
+ */
+ private static boolean doesParameterTypesMatchForVarArgsInvocation(boolean isVarArgs, Class<?>[] parameterTypes,
+ Object[] arguments) {
+ if (isVarArgs && arguments != null && arguments.length >= 1 && parameterTypes != null
+ && parameterTypes.length >= 1) {
+ final Class<?> componentType = parameterTypes[parameterTypes.length - 1].getComponentType();
+ final Object lastArgument = arguments[arguments.length - 1];
+ if (lastArgument != null) {
+ final Class<?> lastArgumentTypeAsPrimitive = getTypeAsPrimitiveIfWrapped(lastArgument);
+ final Class<?> varArgsParameterTypeAsPrimitive = getTypeAsPrimitiveIfWrapped(componentType);
+ isVarArgs = varArgsParameterTypeAsPrimitive.isAssignableFrom(lastArgumentTypeAsPrimitive);
+ }
+ }
+ return isVarArgs && checkArgumentTypesMatchParameterTypes(isVarArgs, parameterTypes, arguments);
+ }
+
+ /**
+ * Get the type of an object and convert it to primitive if the type has a
+ * primitive counter-part. E.g. if object is an instance of
+ * <code>java.lang.Integer</code> this method will return
+ * <code>int.class</code>.
+ *
+ * @param object The object whose type to get.
+ * @return the type as primitive if wrapped
+ */
+ private static Class<?> getTypeAsPrimitiveIfWrapped(Object object) {
+ if (object != null) {
+ final Class<?> firstArgumentType = getType(object);
+ final Class<?> firstArgumentTypeAsPrimitive = PrimitiveWrapper.hasPrimitiveCounterPart(firstArgumentType) ? PrimitiveWrapper
+ .getPrimitiveFromWrapperType(firstArgumentType) : firstArgumentType;
+ return firstArgumentTypeAsPrimitive;
+ }
+ return null;
+ }
+
+ /**
+ * Set the values of multiple instance fields defined in a context using
+ * reflection. The values in the context will be assigned to values on the
+ * <code>instance</code>. This method will traverse the class hierarchy when
+ * searching for the fields. Example usage:
+ * <p/>
+ * Given:
+ * <p/>
+ * <pre>
+ * public class MyContext {
+ * private String myString = "myString";
+ * protected int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private String myInstanceString;
+ * private int myInstanceInt;
+ *
+ * }
+ * </pre>
+ * <p/>
+ * then
+ * <p/>
+ * <pre>
+ * Whitebox.setInternalStateFromContext(new MyInstance(), new MyContext());
+ * </pre>
+ * <p/>
+ * will set the instance variables of <code>myInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ *
+ * @param object the object
+ * @param context The context where the fields are defined.
+ * @param additionalContexts Optionally more additional contexts.
+ */
+ public static void setInternalStateFromContext(Object object, Object context, Object[] additionalContexts) {
+ setInternalStateFromContext(object, context, FieldMatchingStrategy.MATCHING);
+ if (additionalContexts != null && additionalContexts.length > 0) {
+ for (Object additionContext : additionalContexts) {
+ setInternalStateFromContext(object, additionContext, FieldMatchingStrategy.MATCHING);
+ }
+ }
+ }
+
+ public static void setInternalStateFromContext(Object object, Object context, FieldMatchingStrategy strategy) {
+ if (isClass(context)) {
+ copyState(object, getType(context), strategy);
+ } else {
+ copyState(object, context, strategy);
+ }
+ }
+
+ /**
+ * Set the values of multiple static fields defined in a context using
+ * reflection. The values in the context will be assigned to values on the
+ * <code>classOrInstance</code>. This method will traverse the class
+ * hierarchy when searching for the fields. Example usage:
+ * <p/>
+ * Given:
+ * <p/>
+ * <pre>
+ * public class MyContext {
+ * private static String myString = "myString";
+ * protected static int myInt = 9;
+ * }
+ *
+ * public class MyInstance {
+ * private static String myInstanceString;
+ * private static int myInstanceInt;
+ *
+ * }
+ * </pre>
+ * <p/>
+ * then
+ * <p/>
+ * <pre>
+ * Whitebox.setInternalStateFromContext(MyInstance.class, MyContext.class);
+ * </pre>
+ * <p/>
+ * will set the static variables of <code>MyInstance</code> to the values
+ * specified in <code>MyContext</code>.
+ *
+ * @param object the object
+ * @param context The context where the fields are defined.
+ * @param additionalContexts Optionally more additional contexts.
+ */
+ public static void setInternalStateFromContext(Object object, Class<?> context, Class<?>[] additionalContexts) {
+ setInternalStateFromContext(object, context, FieldMatchingStrategy.MATCHING);
+ if (additionalContexts != null && additionalContexts.length > 0) {
+ for (Class<?> additionContext : additionalContexts) {
+ setInternalStateFromContext(object, additionContext, FieldMatchingStrategy.MATCHING);
+ }
+ }
+ }
+
+ /**
+ * Copy state.
+ *
+ * @param object the object
+ * @param context the context
+ * @param strategy The field matching strategy.
+ */
+ static void copyState(Object object, Object context, FieldMatchingStrategy strategy) {
+ if (object == null) {
+ throw new IllegalArgumentException("object to set state cannot be null");
+ } else if (context == null) {
+ throw new IllegalArgumentException("context cannot be null");
+ } else if (strategy == null) {
+ throw new IllegalArgumentException("strategy cannot be null");
+ }
+
+ Set<Field> allFields = isClass(context) ? getAllStaticFields(getType(context)) : getAllInstanceFields(context);
+ for (Field field : allFields) {
+ try {
+ final boolean isStaticField = Modifier.isStatic(field.getModifiers());
+ setInternalState(isStaticField ? getType(object) : object, field.getType(), field.get(context));
+ } catch (FieldNotFoundException e) {
+ if (strategy == FieldMatchingStrategy.STRICT) {
+ throw e;
+ }
+ } catch (IllegalAccessException e) {
+ // Should never happen
+ throw new RuntimeException(
+ "Internal Error: Failed to get the field value in method setInternalStateFromContext.", e);
+ }
+ }
+ }
+
+ /**
+ * Assert object in get internal state is not null.
+ *
+ * @param object the object
+ */
+ private static void assertObjectInGetInternalStateIsNotNull(Object object) {
+ if (object == null) {
+ throw new IllegalArgumentException("The object containing the field cannot be null");
+ }
+ }
+
+ /**
+ * Convert parameter types to primitive.
+ *
+ * @param parameterTypes the parameter types
+ * @return the class[]
+ */
+ private static Class<?>[] convertParameterTypesToPrimitive(Class<?>[] parameterTypes) {
+ Class<?>[] converted = new Class<?>[parameterTypes.length];
+ for (int i = 0; i < parameterTypes.length; i++) {
+ Class<?> primitiveWrapperType = PrimitiveWrapper.getPrimitiveFromWrapperType(parameterTypes[i]);
+ if (primitiveWrapperType == null) {
+ converted[i] = parameterTypes[i];
+ } else {
+ converted[i] = primitiveWrapperType;
+ }
+ }
+ return converted;
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/comparator/ComparatorFactory.java b/reflect/src/main/java/org/powermock/reflect/internal/comparator/ComparatorFactory.java
new file mode 100644
index 0000000..810d963
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/comparator/ComparatorFactory.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.reflect.internal.comparator;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+/**
+ * This comparator factory is used to create Comparators for
+ * {@link org.powermock.reflect.Whitebox} which are used to find best candidates
+ * for constructor and method invocation.
+ * @see org.powermock.reflect.internal.WhiteboxImpl#getBestMethodCandidate(Class, String, Class[], boolean)
+ * @see org.powermock.reflect.internal.WhiteboxImpl#getBestCandidateConstructor(Class, Class[], Object[])
+ * @see org.powermock.reflect.internal.CandidateConstructorSearcher
+ */
+public class ComparatorFactory {
+
+ private ComparatorFactory() {
+ }
+
+ public static Comparator<Constructor> createConstructorComparator(){
+ return new ConstructorComparator(new ParametersComparator());
+ }
+
+ public static Comparator<Method> createMethodComparator(){
+ return new MethodComparator(new ParametersComparator());
+ }
+
+
+ public static class ConstructorComparator implements Comparator<Constructor> {
+ private final ParametersComparator parametersComparator;
+
+ private ConstructorComparator(ParametersComparator parametersComparator) {
+
+ this.parametersComparator = parametersComparator;
+ }
+
+ @Override
+ public int compare(Constructor constructor1, Constructor constructor2) {
+ final Class<?>[] parameters1 = constructor1.getParameterTypes();
+ final Class<?>[] parameters2 = constructor2.getParameterTypes();
+ return parametersComparator.compare(parameters1,parameters2);
+ }
+ }
+
+ /**
+ *
+ */
+ public static class MethodComparator implements Comparator<Method> {
+ private final ParametersComparator parametersComparator;
+
+ private MethodComparator(ParametersComparator parametersComparator) {
+
+ this.parametersComparator = parametersComparator;
+ }
+
+ @Override
+ public int compare(Method m1, Method m2) {
+ final Class<?>[] typesMethod1 = m1.getParameterTypes();
+ final Class<?>[] typesMethod2 = m2.getParameterTypes();
+ return parametersComparator.compare(typesMethod1, typesMethod2);
+
+ }
+ }
+
+ private static class ParametersComparator implements Comparator<Class[]>{
+
+ @Override
+ public int compare(Class[] params1, Class[] params2) {
+ final int size = params1.length;
+ for (int i = 0; i < size; i++) {
+ Class<?> type1 = params1[i];
+ Class<?> type2 = params2[i];
+ if (!type1.equals(type2)) {
+ if (type1.isAssignableFrom(type2)) {
+ if (!type1.isArray() && type2.isArray()) {
+ return -1;
+ }
+ return 1;
+ } else {
+ if (type1.isArray() && !type2.isArray()) {
+ return 1;
+ }
+ return -1;
+ }
+ }
+ }
+ return 0;
+ }
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AllFieldsMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AllFieldsMatcherStrategy.java
new file mode 100644
index 0000000..fc71e6f
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AllFieldsMatcherStrategy.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+
+import java.lang.reflect.Field;
+
+public class AllFieldsMatcherStrategy extends FieldMatcherStrategy {
+
+ @Override
+ public boolean matches(Field field) {
+ return true;
+ }
+
+ @Override
+ public void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException {
+ throw new FieldNotFoundException(String.format("No %s fields were declared in %s.", isInstanceField ? "instance" : "static", type.getName()));
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableFromFieldTypeMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableFromFieldTypeMatcherStrategy.java
new file mode 100644
index 0000000..13074ff
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableFromFieldTypeMatcherStrategy.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+import org.powermock.reflect.internal.primitivesupport.PrimitiveWrapper;
+
+import java.lang.reflect.Field;
+
+public class AssignableFromFieldTypeMatcherStrategy extends FieldTypeMatcherStrategy {
+
+ private final Class<?> primitiveCounterpart;
+
+ public AssignableFromFieldTypeMatcherStrategy(Class<?> fieldType) {
+ super(fieldType);
+ primitiveCounterpart = PrimitiveWrapper.getPrimitiveFromWrapperType(expectedFieldType);
+ }
+
+ @Override
+ public boolean matches(Field field) {
+ Class<?> actualFieldType = field.getType();
+ return actualFieldType.isAssignableFrom(expectedFieldType)
+ || (primitiveCounterpart != null && actualFieldType.isAssignableFrom(primitiveCounterpart));
+ }
+
+ @Override
+ public void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException {
+ throw new FieldNotFoundException(String.format("No %s field assignable from \"%s\" could be found in the class hierarchy of %s.",
+ isInstanceField ? "instance" : "static", expectedFieldType.getName(), type.getName()));
+ }
+
+ @Override
+ public String toString() {
+ return "type " + (primitiveCounterpart == null ? expectedFieldType.getName() : primitiveCounterpart.getName());
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableToFieldTypeMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableToFieldTypeMatcherStrategy.java
new file mode 100644
index 0000000..ee3427a
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/AssignableToFieldTypeMatcherStrategy.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import java.lang.reflect.Field;
+
+public class AssignableToFieldTypeMatcherStrategy extends FieldTypeMatcherStrategy {
+
+ public AssignableToFieldTypeMatcherStrategy(Class<?> fieldType) {
+ super(fieldType);
+ }
+
+ @Override
+ public boolean matches(Field field) {
+ return expectedFieldType.isAssignableFrom((Class<?>) field.getType());
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldAnnotationMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldAnnotationMatcherStrategy.java
new file mode 100644
index 0000000..4f161c3
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldAnnotationMatcherStrategy.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+
+public class FieldAnnotationMatcherStrategy extends FieldMatcherStrategy {
+
+ final Class<? extends Annotation>[] annotations;
+
+ public FieldAnnotationMatcherStrategy(Class<? extends Annotation>[] annotations) {
+ if (annotations == null || annotations.length == 0) {
+ throw new IllegalArgumentException("You must specify atleast one annotation.");
+ }
+ this.annotations = annotations;
+ }
+
+ @Override
+ public boolean matches(Field field) {
+ for (Class<? extends Annotation> annotation : annotations) {
+ if (field.isAnnotationPresent(annotation)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException {
+ throw new FieldNotFoundException("No field that has any of the annotation types \"" + getAnnotationNames()
+ + "\" could be found in the class hierarchy of " + type.getName() + ".");
+ }
+
+ @Override
+ public String toString() {
+ return "annotations " + getAnnotationNames();
+ }
+
+ private String getAnnotationNames() {
+ final StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < annotations.length; i++) {
+ builder.append(annotations[i].getName());
+ if (i != annotations.length - 1) {
+ builder.append(", ");
+ }
+ }
+ return builder.toString();
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldMatcherStrategy.java
new file mode 100644
index 0000000..20b32f2
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldMatcherStrategy.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+
+import java.lang.reflect.Field;
+
+/**
+ * Class that should be implemented by field matching strategies.
+ */
+public abstract class FieldMatcherStrategy {
+
+ /**
+ * A field matcher that checks if a field matches a given criteria.
+ *
+ * @param field
+ * The field to check whether it matches the strategy or not.
+ * @return <code>true</code> if this field matches the strategy,
+ * <code>false</code> otherwise.
+ *
+ */
+ public abstract boolean matches(Field field);
+
+ /**
+ * Throws an {@link FieldNotFoundException} if the strategy criteria could
+ * not be found.
+ *
+ * @param type
+ * The type of the object that was not found.
+ * @param isInstanceField
+ * <code>true</code> if the field that was looked after was an
+ * instance field or <code>false</code> if it was a static field.
+ */
+ public abstract void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException;
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldNameMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldNameMatcherStrategy.java
new file mode 100644
index 0000000..6a2435b
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldNameMatcherStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+
+import java.lang.reflect.Field;
+
+public class FieldNameMatcherStrategy extends FieldMatcherStrategy {
+
+ private final String fieldName;
+
+ public FieldNameMatcherStrategy(String fieldName) {
+ if (fieldName == null || fieldName.equals("") || fieldName.startsWith(" ")) {
+ throw new IllegalArgumentException("field name cannot be null.");
+ }
+ this.fieldName = fieldName;
+ }
+
+ @Override
+ public boolean matches(Field field) {
+ return fieldName.equals(field.getName());
+ }
+
+ @Override
+ public void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException {
+ throw new FieldNotFoundException(String.format("No %s field named \"%s\" could be found in the class hierarchy of %s.",
+ isInstanceField ? "instance" : "static", fieldName, type.getName()));
+ }
+
+ @Override
+ public String toString() {
+ return "fieldName " + fieldName;
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldTypeMatcherStrategy.java b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldTypeMatcherStrategy.java
new file mode 100644
index 0000000..160115d
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/matcherstrategies/FieldTypeMatcherStrategy.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.matcherstrategies;
+
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+
+import java.lang.reflect.Field;
+
+public class FieldTypeMatcherStrategy extends FieldMatcherStrategy {
+
+ final Class<?> expectedFieldType;
+
+ public FieldTypeMatcherStrategy(Class<?> fieldType) {
+ if (fieldType == null) {
+ throw new IllegalArgumentException("field type cannot be null.");
+ }
+ this.expectedFieldType = fieldType;
+ }
+
+ @Override
+ public boolean matches(Field field) {
+ return expectedFieldType.equals(field.getType());
+ }
+
+ @Override
+ public void notFound(Class<?> type, boolean isInstanceField) throws FieldNotFoundException {
+ throw new FieldNotFoundException(String.format("No %s field of type \"%s\" could be found in the class hierarchy of %s.",
+ isInstanceField ? "instance" : "static", expectedFieldType.getName(), type.getName()));
+ }
+
+ @Override
+ public String toString() {
+ return "type " + expectedFieldType.getName();
+ }
+}
\ No newline at end of file
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/BoxedWrapper.java b/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/BoxedWrapper.java
new file mode 100644
index 0000000..6655420
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/BoxedWrapper.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.primitivesupport;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The purpose of the Primitive Wrapper is to provide methods that deals with
+ * translating wrapper types to its related primitive type.
+ */
+public class BoxedWrapper {
+ private static final Map<Class<?>, Class<?>> boxedWrapper = new HashMap<Class<?>, Class<?>>();
+
+ static {
+ boxedWrapper.put(int.class, Integer.class);
+ boxedWrapper.put(long.class, Long.class);
+ boxedWrapper.put(float.class, Float.class);
+ boxedWrapper.put(double.class, Double.class);
+ boxedWrapper.put(boolean.class, Boolean.class);
+ boxedWrapper.put(byte.class, Byte.class);
+ boxedWrapper.put(short.class, Short.class);
+ boxedWrapper.put(char.class, Character.class);
+ }
+
+ /**
+ * Get the wrapped counter part from a primitive type. For example:
+ * <p>
+ *
+ * <code>getBoxedFromPrimitiveType(int.class)</code> will return
+ * <code>Integer.class</code>.
+ *
+ *
+ * @param primitiveType
+ * The primitive type to convert to its wrapper counter part.
+ * @return The boxed counter part or <code>null</code> if the class did
+ * not have a boxed counter part.
+ *
+ */
+ public static Class<?> getBoxedFromPrimitiveType(Class<?> primitiveType) {
+ return boxedWrapper.get(primitiveType);
+ }
+
+ /**
+ * Returns <code>true</code> if <code>type</code> has a primitive
+ * counter-part. E.g. if <code>type</code> if <code>Integer</code> then this
+ * method will return <code>true</code>.
+ *
+ * @param type
+ * The type to check whether or not it has a primitive
+ * counter-part.
+ * @return <code>true</code> if this type has a primitive counter-part.
+ */
+ public static boolean hasBoxedCounterPart(Class<?> type) {
+ return boxedWrapper.containsKey(type);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/PrimitiveWrapper.java b/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/PrimitiveWrapper.java
new file mode 100644
index 0000000..d16c3fc
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/internal/primitivesupport/PrimitiveWrapper.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal.primitivesupport;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The purpose of the Primitive Wrapper is to provide methods that deals with
+ * translating wrapper types to its related primitive type.
+ */
+public class PrimitiveWrapper {
+ private static final Map<Class<?>, Class<?>> primitiveWrapper = new HashMap<Class<?>, Class<?>>();
+
+ static {
+ primitiveWrapper.put(Integer.class, int.class);
+ primitiveWrapper.put(Long.class, long.class);
+ primitiveWrapper.put(Float.class, float.class);
+ primitiveWrapper.put(Double.class, double.class);
+ primitiveWrapper.put(Boolean.class, boolean.class);
+ primitiveWrapper.put(Byte.class, byte.class);
+ primitiveWrapper.put(Short.class, short.class);
+ primitiveWrapper.put(Character.class, char.class);
+ }
+
+ /**
+ * Convert all wrapper types in <code>types</code> to their primitive
+ * counter parts.
+ *
+ * @param types
+ * The array of types that should be converted.
+ * @return A new array where all wrapped types have been converted to their
+ * primitive counter part.
+ */
+ public static Class<?>[] toPrimitiveType(Class<?>[] types) {
+ if (types == null) {
+ throw new IllegalArgumentException("types cannot be null");
+ }
+
+ Class<?>[] convertedTypes = new Class<?>[types.length];
+ for (int i = 0; i < types.length; i++) {
+ final Class<?> originalType = types[i];
+ Class<?> primitiveType = primitiveWrapper.get(originalType);
+ if (primitiveType == null) {
+ convertedTypes[i] = originalType;
+ } else {
+ convertedTypes[i] = primitiveType;
+ }
+ }
+ return convertedTypes;
+ }
+
+ /**
+ * Get the primitive counter part from a wrapped type. For example:
+ * <p>
+ *
+ * <code>getPrimitiveFromWrapperType(Integer.class)</code> will return
+ * <code>int.class</code>.
+ *
+ *
+ * @param wrapperType
+ * The wrapper type to convert to its primitive counter part.
+ * @return The primitive counter part or <code>null</code> if the class did
+ * not have a primitive counter part.
+ *
+ */
+ public static Class<?> getPrimitiveFromWrapperType(Class<?> wrapperType) {
+ return primitiveWrapper.get(wrapperType);
+ }
+
+ /**
+ * Returns <code>true</code> if <code>type</code> has a primitive
+ * counter-part. E.g. if <code>type</code> if <code>Integer</code> then this
+ * method will return <code>true</code>.
+ *
+ * @param type
+ * The type to check whether or not it has a primitive
+ * counter-part.
+ * @return <code>true</code> if this type has a primitive counter-part.
+ */
+ public static boolean hasPrimitiveCounterPart(Class<?> type) {
+ return primitiveWrapper.containsKey(type);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/matching/FieldMatchingStrategy.java b/reflect/src/main/java/org/powermock/reflect/matching/FieldMatchingStrategy.java
new file mode 100644
index 0000000..cc6afaf
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/matching/FieldMatchingStrategy.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.matching;
+
+/**
+ * Defines strategies for field matching.
+ */
+public enum FieldMatchingStrategy {
+ /**
+ * All fields in the context must match <i>exactly</i> the fields in the
+ * target instance or class. This means that an exception will be thrown
+ * unless all fields in the context are found in the target.
+ */
+ STRICT,
+ /**
+ * All fields in the context are copied to the target instance or class. The
+ * context may contain additional fields not present in the target. Only
+ * fields that may be copied from the context to the target are taken into
+ * consideration. An exception will not be thrown if a field exists in the
+ * context but is non-existent in the target.
+ */
+ MATCHING
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/proxyframework/ClassLoaderRegisterProxyFramework.java b/reflect/src/main/java/org/powermock/reflect/proxyframework/ClassLoaderRegisterProxyFramework.java
new file mode 100644
index 0000000..a02b055
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/proxyframework/ClassLoaderRegisterProxyFramework.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.reflect.proxyframework;
+
+/**
+ * Class which use specific class loader to register {@link org.powermock.reflect.spi.ProxyFramework}. This class is
+ * used to avoid class cast exception when a client class (which uses {@link RegisterProxyFramework}) is loaded with
+ * anther class loader.
+ */
+public class ClassLoaderRegisterProxyFramework {
+
+ public static void registerProxyframework(ClassLoader classLoader) {
+ new ProxyFrameworkHelper(classLoader).register();
+ }
+
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/proxyframework/ProxyFrameworkHelper.java b/reflect/src/main/java/org/powermock/reflect/proxyframework/ProxyFrameworkHelper.java
new file mode 100644
index 0000000..cfeb647
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/proxyframework/ProxyFrameworkHelper.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.powermock.reflect.proxyframework;
+
+import org.powermock.reflect.Whitebox;
+
+/**
+ *
+ */
+class ProxyFrameworkHelper {
+ private final ClassLoader classLoader;
+
+ ProxyFrameworkHelper(ClassLoader classLoader) {this.classLoader = classLoader;}
+
+ void register() {
+ final Class<?> proxyFrameworkClass;
+ try {
+ proxyFrameworkClass = Class.forName("org.powermock.api.extension.proxyframework.ProxyFrameworkImpl", false, classLoader);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException("Extension API internal error: org.powermock.api.extension.proxyframework.ProxyFrameworkImpl could not be located in classpath.");
+ }
+
+ final Class<?> proxyFrameworkRegistrar;
+ try {
+ proxyFrameworkRegistrar = Class.forName(RegisterProxyFramework.class.getName(), false, classLoader);
+ } catch (ClassNotFoundException e) {
+ // Should never happen
+ throw new RuntimeException(e);
+ }
+ try {
+ Whitebox.invokeMethod(proxyFrameworkRegistrar, "registerProxyFramework", Whitebox.newInstance(proxyFrameworkClass));
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/proxyframework/RegisterProxyFramework.java b/reflect/src/main/java/org/powermock/reflect/proxyframework/RegisterProxyFramework.java
new file mode 100644
index 0000000..46f9bb4
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/proxyframework/RegisterProxyFramework.java
@@ -0,0 +1,20 @@
+package org.powermock.reflect.proxyframework;
+
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.reflect.spi.ProxyFramework;
+
+/**
+ * All API's must register a proxy framework using this class.
+ */
+public class RegisterProxyFramework {
+
+ /**
+ * Register a proxy framework.
+ *
+ * @param proxyFramework
+ * The proxy framework to register.
+ */
+ public static void registerProxyFramework(ProxyFramework proxyFramework) {
+ WhiteboxImpl.setInternalState(WhiteboxImpl.class, proxyFramework);
+ }
+}
diff --git a/reflect/src/main/java/org/powermock/reflect/spi/ProxyFramework.java b/reflect/src/main/java/org/powermock/reflect/spi/ProxyFramework.java
new file mode 100644
index 0000000..ac32d1f
--- /dev/null
+++ b/reflect/src/main/java/org/powermock/reflect/spi/ProxyFramework.java
@@ -0,0 +1,23 @@
+package org.powermock.reflect.spi;
+
+/**
+ * The purpose of a the proxy framework implementation is to return the
+ * unproxied types of classes.
+ */
+public interface ProxyFramework {
+
+ /**
+ * Check if the class is a proxy and if it is return the unproxied type.
+ *
+ * @param type
+ * The class to check.
+ * @return The unproxied class type.
+ */
+ Class<?> getUnproxiedType(Class<?> type);
+
+ /**
+ * @return <code>true</code> if <tt>type</tt> is a proxy, <code>false</code>
+ * otherwise.
+ */
+ boolean isProxy(Class<?> type);
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/WhiteBoxGetFieldTest.java b/reflect/src/test/java/org/powermock/reflect/WhiteBoxGetFieldTest.java
new file mode 100644
index 0000000..a33835f
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/WhiteBoxGetFieldTest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect;
+
+import junit.framework.Assert;
+import org.junit.Test;
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.lang.reflect.Field;
+
+/**
+ * A test case to demonstrate an issue
+ * {@link org.powermock.reflect.internal.WhiteboxImpl#getField(Class, String)}.
+ * As the class hierarchy for the given Class is ascended, if the field is not
+ * found in the parent class, the interfaces are checked before the grandparent
+ * class. The problem is that the getSuperclass() method will always return null
+ * for the Class representing the interface. The current implementation of
+ * WhiteboxImpl blindly adds this null to the <code>examine</code> LinkedList.
+ *
+ * @author Ben Chatelain
+ */
+public class WhiteBoxGetFieldTest {
+
+ interface SomeInterface {
+ }
+
+ class GrandParentClass {
+ @SuppressWarnings("unused")
+ private String fieldA;
+ }
+
+ class ParentClass extends GrandParentClass {
+ }
+
+ class ClassUnderTest extends ParentClass implements SomeInterface {
+ @SuppressWarnings("unused")
+ private String fieldB;
+ }
+
+ /**
+ * Verifies that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=149">issue
+ * 149</a> has been resolved.
+ */
+ @Test
+ public void testGetField() {
+ Field fieldA = WhiteboxImpl.getField(ClassUnderTest.class, "fieldA");
+ Assert.assertNotNull(fieldA);
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/WhiteBoxTest.java b/reflect/src/test/java/org/powermock/reflect/WhiteBoxTest.java
new file mode 100644
index 0000000..ce08e36
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/WhiteBoxTest.java
@@ -0,0 +1,947 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import org.powermock.reflect.context.ClassFieldsNotInTargetContext;
+import org.powermock.reflect.context.InstanceFieldsNotInTargetContext;
+import org.powermock.reflect.context.MyContext;
+import org.powermock.reflect.context.MyIntContext;
+import org.powermock.reflect.context.MyStringContext;
+import org.powermock.reflect.context.OneInstanceAndOneStaticFieldOfSameTypeContext;
+import org.powermock.reflect.exceptions.FieldNotFoundException;
+import org.powermock.reflect.exceptions.MethodNotFoundException;
+import org.powermock.reflect.exceptions.TooManyFieldsFoundException;
+import org.powermock.reflect.exceptions.TooManyMethodsFoundException;
+import org.powermock.reflect.internal.WhiteboxImpl;
+import org.powermock.reflect.matching.FieldMatchingStrategy;
+import org.powermock.reflect.proxyframework.RegisterProxyFramework;
+import org.powermock.reflect.spi.ProxyFramework;
+import org.powermock.reflect.testclasses.AbstractClass;
+import org.powermock.reflect.testclasses.AnInterface;
+import org.powermock.reflect.testclasses.Child;
+import org.powermock.reflect.testclasses.ClassWithAMethod;
+import org.powermock.reflect.testclasses.ClassWithChildThatHasInternalState;
+import org.powermock.reflect.testclasses.ClassWithInterfaceConstructors;
+import org.powermock.reflect.testclasses.ClassWithInterfaceConstructors.ConstructorInterface;
+import org.powermock.reflect.testclasses.ClassWithInterfaceConstructors.ConstructorInterfaceImpl;
+import org.powermock.reflect.testclasses.ClassWithInternalState;
+import org.powermock.reflect.testclasses.ClassWithList;
+import org.powermock.reflect.testclasses.ClassWithObjectConstructors;
+import org.powermock.reflect.testclasses.ClassWithOverloadedConstructors;
+import org.powermock.reflect.testclasses.ClassWithOverloadedMethods;
+import org.powermock.reflect.testclasses.ClassWithOverriddenMethod;
+import org.powermock.reflect.testclasses.ClassWithPrimitiveConstructors;
+import org.powermock.reflect.testclasses.ClassWithPrivateMethods;
+import org.powermock.reflect.testclasses.ClassWithSerializableState;
+import org.powermock.reflect.testclasses.ClassWithSeveralMethodsWithSameName;
+import org.powermock.reflect.testclasses.ClassWithSeveralMethodsWithSameNameOneWithoutParameters;
+import org.powermock.reflect.testclasses.ClassWithSimpleInternalState;
+import org.powermock.reflect.testclasses.ClassWithStaticAndInstanceInternalStateOfSameType;
+import org.powermock.reflect.testclasses.ClassWithStaticMethod;
+import org.powermock.reflect.testclasses.ClassWithUniquePrivateMethods;
+import org.powermock.reflect.testclasses.ClassWithVarArgsConstructor;
+import org.powermock.reflect.testclasses.ClassWithVarArgsConstructor2;
+
+import java.io.InputStream;
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.sql.Connection;
+import java.util.Set;
+
+import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+/**
+ * Tests the WhiteBox's functionality.
+ */
+public class WhiteBoxTest {
+
+ static {
+ RegisterProxyFramework.registerProxyFramework(new ProxyFramework() {
+ public Class<?> getUnproxiedType(Class<?> type) {
+ return type;
+ }
+
+ public boolean isProxy(Class<?> type) {
+ return false;
+ }
+ });
+ }
+
+ @Test
+ public void testFindMethod_classContainingMethodWithNoParameters() throws Exception {
+ Method expected = ClassWithSeveralMethodsWithSameNameOneWithoutParameters.class.getMethod("getDouble");
+ Method actual = WhiteboxImpl.findMethodOrThrowException(
+ ClassWithSeveralMethodsWithSameNameOneWithoutParameters.class, "getDouble");
+ assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testFindMethod_classContainingOnlyMethodsWithParameters() throws Exception {
+ try {
+ WhiteboxImpl.findMethodOrThrowException(ClassWithSeveralMethodsWithSameName.class, "getDouble");
+ fail("Should throw runtime exception!");
+ } catch (RuntimeException e) {
+ assertTrue("Error message did not match", e.getMessage().contains(
+ "Several matching methods found, please specify the argument parameter types"));
+ }
+ }
+
+ @Test
+ public void testFindMethod_noMethodFound() throws Exception {
+ try {
+ WhiteboxImpl.findMethodOrThrowException(ClassWithSeveralMethodsWithSameName.class, "getDouble2");
+ fail("Should throw runtime exception!");
+ } catch (RuntimeException e) {
+ assertEquals("Error message did not match",
+ "No method found with name 'getDouble2' with parameter types: [ <none> ] in class "
+ + ClassWithSeveralMethodsWithSameName.class.getName() + ".", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetInternalState_object() throws Exception {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ tested.increaseInteralState();
+ Object internalState = Whitebox.getInternalState(tested, "internalState");
+ assertTrue("InternalState should be instanceof Integer", internalState instanceof Integer);
+ assertEquals(1, internalState);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testGetInternalState_parmaterizedType() throws Exception {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ tested.increaseInteralState();
+ int internalState = Whitebox.getInternalState(tested, "internalState", tested.getClass(), int.class);
+ assertEquals(1, internalState);
+ }
+
+ @Test
+ public void testSetInternalState() throws Exception {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ tested.increaseInteralState();
+ Whitebox.setInternalState(tested, "anotherInternalState", 2);
+ assertEquals(2, tested.getAnotherInternalState());
+ }
+
+ @Test
+ public void testSetInternalStateWithMultipleValues() throws Exception {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ final ClassWithPrivateMethods classWithPrivateMethods = new ClassWithPrivateMethods();
+ final String stringState = "someStringState";
+ Whitebox.setInternalState(tested, classWithPrivateMethods, stringState);
+ assertEquals(stringState, Whitebox.getInternalState(tested, String.class));
+ assertSame(classWithPrivateMethods, Whitebox.getInternalState(tested, ClassWithPrivateMethods.class));
+ }
+
+ @Test
+ public void testSetInternalState_superClass() throws Exception {
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ tested.increaseInteralState();
+ Whitebox.setInternalState(tested, "anotherInternalState", 2, ClassWithInternalState.class);
+ assertEquals(2, tested.getAnotherInternalState());
+ }
+
+ @Test
+ public void testGetInternalState_superClass_object() throws Exception {
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Object internalState = Whitebox.getInternalState(tested, "internalState", ClassWithInternalState.class);
+ assertEquals(0, internalState);
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testGetInternalState_superClass_parameterized() throws Exception {
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ int internalState = Whitebox.getInternalState(tested, "internalState", ClassWithInternalState.class, int.class);
+ assertEquals(0, internalState);
+ }
+
+ @Test
+ public void testInvokePrivateMethod_primtiveType() throws Exception {
+ assertTrue(Whitebox.<Boolean> invokeMethod(new ClassWithPrivateMethods(), "primitiveMethod", 8.2));
+ }
+
+ @Test
+ public void testInvokePrivateMethod_primtiveType_withoutSpecifyingMethodName() throws Exception {
+ assertTrue((Boolean) Whitebox.invokeMethod(new ClassWithUniquePrivateMethods(), 8.2d, 8.4d));
+ }
+
+ /**
+ * This test actually invokes the <code>finalize</code> method of
+ * <code>java.lang.Object</code> because we supply no method name and no
+ * arguments. <code>finalize</code> is thus the first method found and it'll
+ * be executed.
+ *
+ * @throws Exception
+ */
+ @Test
+ @Ignore("Invokes different methods on PC and MAC (hashCode on mac)")
+ public void testInvokePrivateMethod_withoutSpecifyingMethodName_noArguments() throws Exception {
+ assertNull(Whitebox.invokeMethod(new ClassWithUniquePrivateMethods()));
+ }
+
+ @Test
+ public void testInvokePrivateMethod_withoutSpecifyingMethodName_assertThatNullWorks() throws Exception {
+ assertTrue(Whitebox.invokeMethod(new ClassWithUniquePrivateMethods(), 8.2d, 8.3d, null) instanceof Object);
+ }
+
+ /**
+ * This test should actually fail since equals takes an Object and we pass
+ * in a primitive wrapped as a Double. Thus PowerMock cannot determine
+ * whether to invoke the single argument method defined in
+ * {@link ClassWithUniquePrivateMethods} or the
+ * {@link Object#equals(Object)} method because we could potentially invoke
+ * equals with a Double.
+ */
+ @Test(expected = TooManyMethodsFoundException.class)
+ public void testInvokePrivateMethod_withoutSpecifyingMethodName_onlyOneArgument() throws Exception {
+ Whitebox.invokeMethod(new ClassWithUniquePrivateMethods(), 8.2d);
+ }
+
+ @Test(expected = TooManyMethodsFoundException.class)
+ public void testInvokeStaticPrivateMethod_withoutSpecifyingMethodName_onlyOneArgument() throws Exception {
+ assertTrue((Boolean) Whitebox.invokeMethod(ClassWithUniquePrivateMethods.class, 8.2d));
+ }
+
+ @Test
+ public void testInvokePrivateMethod_primtiveType_Wrapped() throws Exception {
+ assertTrue((Boolean) Whitebox.invokeMethod(new ClassWithPrivateMethods(), "primitiveMethod", new Double(8.2)));
+ }
+
+ @Test
+ public void testInvokePrivateMethod_wrappedType() throws Exception {
+ assertTrue((Boolean) Whitebox.invokeMethod(new ClassWithPrivateMethods(), "wrappedMethod", new Double(8.2)));
+ }
+
+ @Test
+ public void testInvokePrivateMethod_wrappedType_primitive() throws Exception {
+ assertTrue((Boolean) Whitebox.invokeMethod(new ClassWithPrivateMethods(), "wrappedMethod", 8.2));
+ }
+
+ @Test
+ public void testMethodWithPrimitiveIntAndString_primitive() throws Exception {
+ assertEquals("My int value is: " + 8, (String) Whitebox.invokeMethod(new ClassWithPrivateMethods(),
+ "methodWithPrimitiveIntAndString", 8, "My int value is: "));
+ }
+
+ @Test
+ public void testMethodWithPrimitiveIntAndString_Wrapped() throws Exception {
+ assertEquals("My int value is: " + 8, (String) Whitebox.invokeMethod(new ClassWithPrivateMethods(),
+ "methodWithPrimitiveIntAndString", Integer.valueOf(8), "My int value is: "));
+ }
+
+ @Test
+ public void testMethodWithPrimitiveAndWrappedInt_primtive_wrapped() throws Exception {
+ assertEquals(17, Whitebox.invokeMethod(new ClassWithPrivateMethods(), "methodWithPrimitiveAndWrappedInt",
+ new Class[] { int.class, Integer.class }, 9, Integer.valueOf(8)));
+ }
+
+ @Test
+ public void testStaticState() {
+ int expected = 123;
+ Whitebox.setInternalState(ClassWithInternalState.class, "staticState", expected);
+ assertEquals(expected, ClassWithInternalState.getStaticState());
+ assertEquals(expected, Whitebox.getInternalState(ClassWithInternalState.class, "staticState"));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void testStaticFinalState() {
+ Whitebox.setInternalState(ClassWithInternalState.class, "staticFinalState", 123);
+ fail("Static final is not possible to change");
+ }
+
+ /**
+ * Verifies that the http://code.google.com/p/powermock/issues/detail?id=6
+ * is fixed.
+ *
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvokeMethodWithNullParameter() throws Exception {
+ Whitebox.invokeMethod(null, "method");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testInvokeConstructorWithNullParameter() throws Exception {
+ Whitebox.invokeConstructor(null, "constructor");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testGetInternalWithNullParameter() throws Exception {
+ Whitebox.getInternalState(null, "state");
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetInternalWithNullParameter() throws Exception {
+ Whitebox.setInternalState(null, "state", new Object());
+ }
+
+ @Test
+ public void testInstantiateVarArgsOnlyConstructor() throws Exception {
+ final String argument1 = "argument1";
+ final String argument2 = "argument2";
+ ClassWithVarArgsConstructor instance = Whitebox.invokeConstructor(ClassWithVarArgsConstructor.class, argument1,
+ argument2);
+ String[] strings = instance.getStrings();
+ assertEquals(2, strings.length);
+ assertEquals(argument1, strings[0]);
+ assertEquals(argument2, strings[1]);
+ }
+
+ @Test
+ public void testInstantiateVarArgsOnlyConstructor_noArguments() throws Exception {
+ ClassWithVarArgsConstructor instance = Whitebox.invokeConstructor(ClassWithVarArgsConstructor.class);
+ String[] strings = instance.getStrings();
+ assertEquals(0, strings.length);
+ }
+
+ @Test
+ public void testInvokeVarArgsMethod_multipleValues() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(6, Whitebox.invokeMethod(tested, "varArgsMethod", 1, 2, 3));
+ }
+
+ @Test
+ public void testInvokeVarArgsMethod_noArguments() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(0, Whitebox.invokeMethod(tested, "varArgsMethod"));
+ }
+
+ @Test
+ public void testInvokeVarArgsMethod_oneArgument() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(4, Whitebox.invokeMethod(tested, "varArgsMethod", 2));
+ }
+
+ @Test
+ public void testInvokeVarArgsMethod_invokeVarArgsWithOneArgument() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(1, Whitebox.invokeMethod(tested, "varArgsMethod", new Class<?>[] { int[].class }, 1));
+ }
+
+ @Test
+ public void testInvokePrivateMethodWithASubTypeOfTheArgumentType() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ ClassWithChildThatHasInternalState argument = new ClassWithChildThatHasInternalState();
+ assertSame(argument, Whitebox.invokeMethod(tested, "methodWithObjectArgument", argument));
+ }
+
+ @Test
+ public void testInvokePrivateMethodWithAClassArgument() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(ClassWithChildThatHasInternalState.class, Whitebox.invokeMethod(tested, "methodWithClassArgument",
+ ClassWithChildThatHasInternalState.class));
+ }
+
+ @Test
+ public void testSetInternalStateInChildClassWithoutSpecifyingTheChildClass() throws Exception {
+ final int value = 22;
+ final String fieldName = "internalState";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState() {
+ };
+ Whitebox.setInternalState(tested, fieldName, value);
+ assertEquals(value, Whitebox.getInternalState(tested, fieldName));
+ }
+
+ @Test
+ public void testSetInternalStateInClassAndMakeSureThatTheChildClassIsNotAffectedEvenThoughItHasAFieldWithTheSameName()
+ throws Exception {
+ final int value = 22;
+ final String fieldName = "anotherInternalState";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState() {
+ };
+ Whitebox.setInternalState(tested, fieldName, value);
+ assertEquals(value, Whitebox.getInternalState(tested, fieldName));
+ assertEquals(-1, Whitebox.getInternalState(tested, fieldName, ClassWithInternalState.class));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetInternalStateWithInvalidArgumentType() throws Exception {
+ final int value = 22;
+ final String fieldName = "internalState";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState() {
+ };
+ Whitebox.setInternalState(tested, fieldName, new Object());
+ assertEquals(value, Whitebox.getInternalState(tested, fieldName));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testSetInternalStateWithNull() throws Exception {
+ final int value = 22;
+ final String fieldName = "internalState";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState() {
+ };
+ Whitebox.setInternalState(tested, fieldName, (Object) null);
+ assertEquals(value, Whitebox.getInternalState(tested, fieldName));
+ }
+
+ @Test
+ public void testSetAndGetInternalStateBasedOnFieldType() throws Exception {
+ final int value = 22;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, int.class, value);
+ assertEquals(value, (int) Whitebox.getInternalState(tested, int.class));
+ assertEquals(value, Whitebox.getInternalState(tested, "anotherInternalState"));
+ assertEquals(value, Whitebox.getInternalState(tested, "anotherInternalState",
+ ClassWithChildThatHasInternalState.class));
+ }
+
+ @Test
+ public void testSetAndGetInternalStateAtASpecificPlaceInTheHierarchyBasedOnFieldType() throws Exception {
+ final int value = 22;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, int.class, value, ClassWithInternalState.class);
+ assertEquals(42, (int) Whitebox.getInternalState(tested, int.class));
+ assertEquals(value, (int) Whitebox.getInternalState(tested, int.class, ClassWithInternalState.class));
+ assertEquals(value, Whitebox.getInternalState(tested, "staticState", ClassWithInternalState.class));
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectType() throws Exception {
+ final String value = "a string";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value);
+ assertEquals(value, Whitebox.getInternalState(tested, String.class));
+ }
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testSetInternalStateBasedOnObjectTypeWhenArgumentIsAPrimitiveType() throws Exception {
+ final int value = 22;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value);
+ assertEquals((Integer) value, Whitebox.getInternalState(tested, "anotherInternalState",
+ ClassWithChildThatHasInternalState.class, Integer.class));
+ }
+
+ public void testSetInternalStateBasedOnObjectTypeWhenArgumentIsAPrimitiveTypeUsingGenerics() throws Exception {
+ final int value = 22;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value);
+ assertEquals((Integer) value, Whitebox.<Integer> getInternalState(tested, "anotherInternalState",
+ ClassWithChildThatHasInternalState.class));
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectTypeAtASpecificPlaceInTheClassHierarchy() throws Exception {
+ final String value = "a string";
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, (Object) value, ClassWithInternalState.class);
+ assertEquals(value, Whitebox.getInternalState(tested, "finalString"));
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectTypeAtASpecificPlaceInTheClassHierarchyForPrimitiveType()
+ throws Exception {
+ final long value = 31;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value, ClassWithInternalState.class);
+ assertEquals(value, tested.getInternalLongState());
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectTypeAtANonSpecificPlaceInTheClassHierarchyForPrimitiveType()
+ throws Exception {
+ final long value = 31;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value);
+ assertEquals(value, tested.getInternalLongState());
+ }
+
+ @Test
+ public void testSetInternalMultipleOfSameTypeOnSpecificPlaceInHierarchy() throws Exception {
+ final int value = 31;
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ try {
+ Whitebox.setInternalState(tested, value, ClassWithInternalState.class);
+ fail("should throw TooManyFieldsFoundException!");
+ } catch (TooManyFieldsFoundException e) {
+ assertEquals("Two or more fields matching type int.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetInternalMultipleOfSameType() throws Exception {
+ final int value = 31;
+ ClassWithInternalState tested = new ClassWithInternalState();
+ try {
+ Whitebox.setInternalState(tested, value);
+ fail("should throw TooManyFieldsFoundException!");
+ } catch (TooManyFieldsFoundException e) {
+ assertEquals("Two or more fields matching type int.", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectSubClassTypeAtASpecificPlaceInTheClassHierarchy() throws Exception {
+ final ClassWithPrivateMethods value = new ClassWithPrivateMethods() {
+ };
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState();
+ Whitebox.setInternalState(tested, value, ClassWithInternalState.class);
+ assertSame(value, tested.getClassWithPrivateMethods());
+ }
+
+ @Test
+ public void testSetInternalStateBasedOnObjectSubClassType() throws Exception {
+ final ClassWithPrivateMethods value = new ClassWithPrivateMethods() {
+ };
+ ClassWithChildThatHasInternalState tested = new ClassWithChildThatHasInternalState() {
+ };
+ Whitebox.setInternalState(tested, value);
+ assertSame(value, tested.getClassWithPrivateMethods());
+ }
+
+ @Test
+ public void testGetAllInstanceFields() throws Exception {
+ Set<Field> allFields = Whitebox.getAllInstanceFields(new ClassWithChildThatHasInternalState());
+ assertEquals(8, allFields.size());
+ }
+
+ @Test
+ public void testGetAllStaticFields_assertNoFieldsFromParent() throws Exception {
+ Set<Field> allFields = Whitebox.getAllStaticFields(ClassWithChildThatHasInternalState.class);
+ assertEquals(0, allFields.size());
+ }
+
+ @Test
+ public void testGetAllStaticFields() throws Exception {
+ Set<Field> allFields = Whitebox.getAllStaticFields(ClassWithInternalState.class);
+ assertEquals(2, allFields.size());
+ }
+
+ @Test
+ public void testMethodWithNoMethodName_noMethodFound() throws Exception {
+ try {
+ Whitebox.getMethod(ClassWithInternalState.class, int.class);
+ fail("Should throw MethodNotFoundException");
+ } catch (MethodNotFoundException e) {
+ assertEquals(
+ "No method was found with parameter types: [ int ] in class org.powermock.reflect.testclasses.ClassWithInternalState.",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMethodWithNoMethodName_tooManyMethodsFound() throws Exception {
+ try {
+ Whitebox.getMethod(ClassWithSeveralMethodsWithSameName.class);
+ fail("Should throw TooManyMethodsFoundException");
+ } catch (TooManyMethodsFoundException e) {
+ assertTrue(e
+ .getMessage()
+ .contains(
+ "Several matching methods found, please specify the method name so that PowerMock can determine which method you're referring to"));
+ }
+ }
+
+ @Test
+ public void testMethodWithNoMethodName_ok() throws Exception {
+ final Method method = Whitebox.getMethod(ClassWithSeveralMethodsWithSameName.class, double.class);
+ assertEquals(method, ClassWithSeveralMethodsWithSameName.class.getDeclaredMethod("getDouble", double.class));
+ }
+
+ @Test
+ public void testGetTwoMethodsWhenNoneOfThemAreFound() throws Exception {
+ try {
+ Whitebox.getMethods(ClassWithSeveralMethodsWithSameName.class, "notFound1", "notFound2");
+ } catch (MethodNotFoundException e) {
+ assertEquals(
+ "No methods matching the name(s) notFound1 or notFound2 were found in the class hierarchy of class org.powermock.reflect.testclasses.ClassWithSeveralMethodsWithSameName.",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetThreeMethodsWhenNoneOfThemAreFound() throws Exception {
+ try {
+ Whitebox.getMethods(ClassWithSeveralMethodsWithSameName.class, "notFound1", "notFound2", "notFound3");
+ } catch (MethodNotFoundException e) {
+ assertEquals(
+ "No methods matching the name(s) notFound1, notFound2 or notFound3 were found in the class hierarchy of class org.powermock.reflect.testclasses.ClassWithSeveralMethodsWithSameName.",
+ e.getMessage());
+ }
+ }
+
+ /**
+ * Asserts that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=118">issue
+ * 118</a> is fixed. Thanks to cemcatik for finding this.
+ */
+ @Test
+ public void testInvokeConstructorWithBothNormalAndVarArgsParameter() throws Exception {
+ ClassWithVarArgsConstructor2 instance = Whitebox.invokeConstructor(ClassWithVarArgsConstructor2.class, "first",
+ "second", "third");
+ assertArrayEquals(new String[] { "first", "second", "third" }, instance.getStrings());
+ }
+
+ /**
+ * Asserts that <a
+ * href="http://code.google.com/p/powermock/issues/detail?id=118">issue
+ * 118</a> is fixed. Thanks to cemcatik for finding this.
+ */
+ @Test
+ public void testInvokeMethodWithBothNormalAndVarArgsParameter() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals(4, Whitebox.invokeMethod(tested, "varArgsMethod2", 1, 2, 3));
+ }
+
+ @Test
+ public void testInvokePrivateMethodWithArrayArgument() throws Exception {
+ ClassWithPrivateMethods tested = new ClassWithPrivateMethods();
+ assertEquals("Hello World", Whitebox.invokeMethod(tested, "evilConcatOfStrings", new Object[] { new String[] {
+ "Hello ", "World" } }));
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_allStatesInSameOneContext() throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ MyContext context = new MyContext();
+ Whitebox.setInternalStateFromContext(tested, context);
+ assertEquals(context.getMyStringState(), tested.getSomeStringState());
+ assertEquals(context.getMyIntState(), tested.getSomeIntState());
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_statesInDifferentContext() throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ MyIntContext myIntContext = new MyIntContext();
+ MyStringContext myStringContext = new MyStringContext();
+ Whitebox.setInternalStateFromContext(tested, myIntContext, myStringContext);
+ assertEquals(myStringContext.getMyStringState(), tested.getSomeStringState());
+ assertEquals(myIntContext.getSimpleIntState(), tested.getSomeIntState());
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_contextIsAClass() throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ Whitebox.setInternalStateFromContext(tested, MyContext.class);
+ assertEquals((Long) Whitebox.getInternalState(MyContext.class, long.class), (Long) tested
+ .getSomeStaticLongState());
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_contextIsAClassAndAnInstance() throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ MyContext myContext = new MyContext();
+ Whitebox.setInternalStateFromContext(tested, MyContext.class, myContext);
+ assertEquals(myContext.getMyStringState(), tested.getSomeStringState());
+ assertEquals(myContext.getMyIntState(), tested.getSomeIntState());
+ assertEquals((Long) myContext.getMyLongState(), (Long) tested.getSomeStaticLongState());
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_contextHasOneInstanceAndOneStaticFieldOfSameType_onlyInstanceContext()
+ throws Exception {
+ ClassWithStaticAndInstanceInternalStateOfSameType.reset();
+ ClassWithStaticAndInstanceInternalStateOfSameType tested = new ClassWithStaticAndInstanceInternalStateOfSameType();
+ OneInstanceAndOneStaticFieldOfSameTypeContext context = new OneInstanceAndOneStaticFieldOfSameTypeContext();
+ Whitebox.setInternalStateFromContext(tested, context);
+ assertEquals(context.getMyStringState(), tested.getStringState());
+ assertEquals("Static String state", tested.getStaticStringState());
+ }
+
+ @Test
+ public void testSetInternalStateFromContext_contextHasOneInstanceAndOneStaticFieldOfSameType_onlyStaticContext()
+ throws Exception {
+ ClassWithStaticAndInstanceInternalStateOfSameType.reset();
+ ClassWithStaticAndInstanceInternalStateOfSameType tested = new ClassWithStaticAndInstanceInternalStateOfSameType();
+ Whitebox.setInternalStateFromContext(tested, OneInstanceAndOneStaticFieldOfSameTypeContext.class);
+ assertEquals(OneInstanceAndOneStaticFieldOfSameTypeContext.getMyStaticStringState(), tested
+ .getStaticStringState());
+ assertEquals("String state", tested.getStringState());
+ }
+
+ @Test
+ public void setInternalStateFromInstanceContextCopiesMatchingContextFieldsToTargetObjectByDefault()
+ throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ InstanceFieldsNotInTargetContext fieldsNotInTargetContext = new InstanceFieldsNotInTargetContext();
+ assertFalse(tested.getSomeStringState().equals(fieldsNotInTargetContext.getString()));
+ Whitebox.setInternalStateFromContext(tested, fieldsNotInTargetContext);
+ assertEquals(tested.getSomeStringState(), fieldsNotInTargetContext.getString());
+ }
+
+ @Test
+ public void setInternalStateFromInstanceContextCopiesMatchingContextFieldsToTargetObjectWhenSpecifyingMatchingStrategy()
+ throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ InstanceFieldsNotInTargetContext fieldsNotInTargetContext = new InstanceFieldsNotInTargetContext();
+ assertFalse(tested.getSomeStringState().equals(fieldsNotInTargetContext.getString()));
+ Whitebox.setInternalStateFromContext(tested, fieldsNotInTargetContext, FieldMatchingStrategy.MATCHING);
+ assertEquals(tested.getSomeStringState(), fieldsNotInTargetContext.getString());
+ }
+
+ @Test(expected = FieldNotFoundException.class)
+ public void setInternalStateFromInstanceContextThrowsExceptionWhenContextContainsFieldsNotDefinedInTargetObjectWhenSpecifyingStrictStrategy()
+ throws Exception {
+ ClassWithSimpleInternalState tested = new ClassWithSimpleInternalState();
+ InstanceFieldsNotInTargetContext fieldsNotInTargetContext = new InstanceFieldsNotInTargetContext();
+ assertFalse(tested.getSomeStringState().equals(fieldsNotInTargetContext.getString()));
+ Whitebox.setInternalStateFromContext(tested, fieldsNotInTargetContext, FieldMatchingStrategy.STRICT);
+ assertEquals(tested.getSomeStringState(), fieldsNotInTargetContext.getString());
+ }
+
+ @Test
+ public void setInternalStateFromClassContextCopiesMatchingContextFieldsToTargetObjectByDefault() throws Exception {
+ long state = ClassWithSimpleInternalState.getLong();
+ try {
+ assertFalse(state == ClassFieldsNotInTargetContext.getLong());
+ Whitebox.setInternalStateFromContext(ClassWithSimpleInternalState.class,
+ ClassFieldsNotInTargetContext.class);
+ assertEquals(ClassFieldsNotInTargetContext.getLong(), ClassWithSimpleInternalState.getLong());
+ } finally {
+ // Restore the state
+ ClassWithSimpleInternalState.setLong(state);
+ }
+ }
+
+ @Test
+ public void setInternalStateFromClassContextCopiesMatchingContextFieldsToTargetObjectWhenSpecifyingMatchingStrategy()
+ throws Exception {
+ long state = ClassWithSimpleInternalState.getLong();
+ try {
+ assertFalse(state == ClassFieldsNotInTargetContext.getLong());
+ Whitebox.setInternalStateFromContext(ClassWithSimpleInternalState.class,
+ ClassFieldsNotInTargetContext.class, FieldMatchingStrategy.MATCHING);
+ assertEquals(ClassFieldsNotInTargetContext.getLong(), ClassWithSimpleInternalState.getLong());
+ } finally {
+ // Restore the state
+ ClassWithSimpleInternalState.setLong(state);
+ }
+ }
+
+ @Test(expected = FieldNotFoundException.class)
+ public void setInternalStateFromClassContextThrowsExceptionWhenContextContainsFieldsNotDefinedInTargetObjectWhenSpecifyingStrictStrategy()
+ throws Exception {
+ long state = ClassWithSimpleInternalState.getLong();
+ try {
+ assertFalse(state == ClassFieldsNotInTargetContext.getLong());
+ Whitebox.setInternalStateFromContext(ClassWithSimpleInternalState.class,
+ ClassFieldsNotInTargetContext.class, FieldMatchingStrategy.STRICT);
+ } finally {
+ // Restore the state
+ ClassWithSimpleInternalState.setLong(state);
+ }
+ }
+
+ @Test
+ public void assertThatErrorMessageIsCorrectWhenNoInstanceFieldFound() throws Exception {
+ ClassWithInternalState classWithInternalState = new ClassWithInternalState();
+ try {
+ Whitebox.setInternalState(classWithInternalState, (byte) 23);
+ fail("Should throw a FieldNotFoundException.");
+ } catch (FieldNotFoundException e) {
+ assertEquals(
+ "No instance field assignable from \"java.lang.Byte\" could be found in the class hierarchy of "
+ + ClassWithInternalState.class.getName() + ".", e.getMessage());
+ }
+ }
+
+ @Test
+ public void assertThatErrorMessageIsCorrectWhenNoStaticFieldFound() throws Exception {
+ try {
+ Whitebox.setInternalState(ClassWithInternalState.class, (byte) 23);
+ fail("Should throw a FieldNotFoundException.");
+ } catch (FieldNotFoundException e) {
+ assertEquals("No static field assignable from \"java.lang.Byte\" could be found in the class hierarchy of "
+ + ClassWithInternalState.class.getName() + ".", e.getMessage());
+ }
+ }
+
+ @Test
+ public void assertThatWhiteboxWorksWithGenericsWhenSpecifyingFieldName() throws Exception {
+ ClassWithInternalState object = new ClassWithInternalState();
+ Set<String> state = Whitebox.<Set<String>> getInternalState(object, "genericState");
+ assertSame(object.getGenericState(), state);
+ }
+
+ @Test
+ public void whiteboxGetMethodWithCorrectMethodNameButWrongParameterTypeReturnsErrorMessageReflectingTheWrongParameter()
+ throws Exception {
+ try {
+ Whitebox.getMethod(ClassWithInternalState.class, "methodWithArgument", String.class, InputStream.class);
+ fail("Should throw MethodNotFoundException");
+ } catch (MethodNotFoundException e) {
+ assertEquals(
+ "No method found with name 'methodWithArgument' with parameter types: [ java.lang.String, java.io.InputStream ] in class org.powermock.reflect.testclasses.ClassWithInternalState.",
+ e.getMessage());
+ }
+ }
+
+ @Test
+ public void whiteboxSetInternalStateWorksOnArraysWhenDefiningMethodName() {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ final String[] expected = new String[] { "string1", "string2" };
+ Whitebox.setInternalState(tested, "stringArray", expected);
+ assertArrayEquals(expected, tested.getStringArray());
+ }
+
+ @Test
+ public void whiteboxSetInternalStateWorksOnArraysWhenNotDefiningMethodName() {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ final String[] expected = new String[] { "string1", "string2" };
+ Whitebox.setInternalState(tested, expected);
+ assertArrayEquals(expected, tested.getStringArray());
+ }
+
+ @Test
+ public void getInternalStateThrowsIAEWhenInstanceIsNull() {
+ try {
+ Whitebox.getInternalState(null, String.class);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ assertEquals("The object containing the field cannot be null", e.getMessage());
+ }
+ }
+
+ @Test
+ public void getInternalStateSupportsObjectArrayWhenSUTContainsSerializable() {
+ ClassWithSerializableState tested = new ClassWithSerializableState();
+ tested.setSerializable(new Serializable() {
+ private static final long serialVersionUID = -1850246005852779087L;
+ });
+ tested.setObjectArray(new Object[0]);
+ assertNotNull(Whitebox.getInternalState(tested, Object[].class));
+ }
+
+ @Test
+ public void getInternalStateUsesAssignableToWhenLookingForObject() {
+ ClassWithList tested = new ClassWithList();
+ assertNotNull(Whitebox.getInternalState(tested, Object.class));
+ }
+
+ @Test(expected = TooManyFieldsFoundException.class)
+ public void getInternalStateThrowsTooManyFieldsFoundWhenTooManyFieldsMatchTheSuppliedType() {
+ ClassWithInternalState tested = new ClassWithInternalState();
+ assertNotNull(Whitebox.getInternalState(tested, Object.class));
+ }
+
+ @Test
+ public void invokeMethodInvokesOverridenMethods() throws Exception {
+ assertTrue(Whitebox.<Boolean> invokeMethod(new ClassWithOverriddenMethod(), 2.0d));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void newInstanceThrowsIAEWhenClassIsAbstract() throws Exception {
+ Whitebox.newInstance(AbstractClass.class);
+ }
+
+ @Test
+ public void newInstanceReturnsJavaProxyWhenInterface() throws Exception {
+ AnInterface instance = Whitebox.newInstance(AnInterface.class);
+ assertTrue(Proxy.isProxyClass(instance.getClass()));
+ }
+
+ @Test
+ public void newInstanceCreatesAnEmptyArrayWhenClassIsArray() throws Exception {
+ byte[] newInstance = Whitebox.newInstance(byte[].class);
+ assertEquals(0, newInstance.length);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void invokeMethodSupportsNullParameters() throws Exception {
+ ClassWithAMethod classWithAMethod = new ClassWithAMethod();
+ Connection connection = null;
+ Whitebox.invokeMethod(classWithAMethod, "connect", connection);
+ }
+
+ @Test(expected = MethodNotFoundException.class)
+ public void invokeOverriddenMethodWithNullParameterThrowsIAE() throws Exception {
+ ClassWithOverloadedMethods tested = new ClassWithOverloadedMethods();
+ Child child = null;
+ Whitebox.invokeMethod(tested, "overloaded", 2, child);
+ }
+
+ @Test
+ public void canPassNullParamToPrivateStaticMethod() throws Exception {
+ assertEquals("hello", Whitebox.invokeMethod(ClassWithStaticMethod.class, "aStaticMethod", null));
+ }
+
+ @Test
+ public void canPassNullParamToPrivateStaticMethodWhenDefiningParameterTypes() throws Exception {
+ assertEquals("hello", Whitebox.invokeMethod(ClassWithStaticMethod.class, "aStaticMethod", new Class<?>[]{byte[].class},null));
+ }
+
+ @Test
+ public void canPassNullPrimitiveArraysToAPrivateStaticMethod() throws Exception {
+ assertEquals("hello", Whitebox.invokeMethod(ClassWithStaticMethod.class, "aStaticMethod", (byte[]) null));
+ }
+
+ @Test
+ public void canPassMultipleNullValuesToStaticMethod() throws Exception {
+ assertEquals("null null", Whitebox.invokeMethod(ClassWithStaticMethod.class, "anotherStaticMethod", (Object) null, (byte[]) null));
+ }
+
+
+ @Test
+ public void testObjectConstructors() throws Exception{
+ String name = "objectConstructor";
+ ClassWithObjectConstructors instance = Whitebox.invokeConstructor(ClassWithObjectConstructors.class,
+ name);
+
+ assertEquals(instance.getName(),name);
+ }
+
+ @Test
+ public void testInterfaceConstructors() throws Exception{
+ ConstructorInterface param = new ConstructorInterfaceImpl("constructorInterfaceSomeValue");
+ ClassWithInterfaceConstructors instance = Whitebox.invokeConstructor(ClassWithInterfaceConstructors.class,
+ param);
+
+ assertEquals(instance.getValue(),param.getValue());
+ }
+
+ @Test
+ public void testPrimitiveConstructorsArgumentBoxed() throws Exception{
+ Long arg = 1L;
+ ClassWithPrimitiveConstructors instance = Whitebox.invokeConstructor(ClassWithPrimitiveConstructors.class,
+ arg);
+
+ assertEquals(instance.getValue(),arg.longValue());
+ }
+
+ @Test
+ public void testOverloadedConstructors() throws Exception{
+ String name = "overloadedConstructor";
+ ClassWithOverloadedConstructors instance = Whitebox.invokeConstructor(ClassWithOverloadedConstructors.class,
+ true, name);
+
+ assertEquals(instance.getName(),name);
+ assertTrue(instance.isBool());
+ assertFalse(instance.isBool1());
+ }
+
+ @Test
+ @Ignore("Reflection and direct call returns different values.")
+ public void testFinalState() {
+ ClassWithInternalState state = new ClassWithInternalState();
+ String expected = "changed";
+ Whitebox.setInternalState(state, "finalString", expected);
+ assertEquals(expected, state.getFinalString());
+ assertEquals(expected, Whitebox.getInternalState(state, "finalString"));
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/context/ClassFieldsNotInTargetContext.java b/reflect/src/test/java/org/powermock/reflect/context/ClassFieldsNotInTargetContext.java
new file mode 100644
index 0000000..9a71386
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/ClassFieldsNotInTargetContext.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The purpose of this context is that it should define fields not available in
+ * the target object to where the state is supposed to be copied.
+ */
+public class ClassFieldsNotInTargetContext {
+ private static long something = 42L;
+
+ private static Map<?, ?> map = new HashMap<Object, Object>();
+
+ public static long getLong() {
+ return something;
+ }
+
+ public static Map<?, ?> getMap() {
+ return map;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/context/InstanceFieldsNotInTargetContext.java b/reflect/src/test/java/org/powermock/reflect/context/InstanceFieldsNotInTargetContext.java
new file mode 100644
index 0000000..a54a6ea
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/InstanceFieldsNotInTargetContext.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * The purpose of this context is that it should define fields not available in
+ * the target object to where the state is supposed to be copied.
+ */
+public class InstanceFieldsNotInTargetContext {
+ private String something = "something";
+
+ private Map<?, ?> map = new HashMap<Object, Object>();
+
+ public String getString() {
+ return something;
+ }
+
+ public Map<?, ?> getMap() {
+ return map;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/context/MyContext.java b/reflect/src/test/java/org/powermock/reflect/context/MyContext.java
new file mode 100644
index 0000000..f00cb1e
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/MyContext.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+public class MyContext {
+ private int myIntState = 42;
+
+ private String myStringState = "myString";
+
+ private static long myLongState = 21L;
+
+ public long getMyLongState() {
+ return myLongState;
+ }
+
+ public int getMyIntState() {
+ return myIntState;
+ }
+
+ public String getMyStringState() {
+ return myStringState;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/context/MyIntContext.java b/reflect/src/test/java/org/powermock/reflect/context/MyIntContext.java
new file mode 100644
index 0000000..dbd94bf
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/MyIntContext.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+public class MyIntContext {
+
+ private int simpleIntState = 42;
+
+ public int getSimpleIntState() {
+ return simpleIntState;
+ }
+}
+
diff --git a/reflect/src/test/java/org/powermock/reflect/context/MyStringContext.java b/reflect/src/test/java/org/powermock/reflect/context/MyStringContext.java
new file mode 100644
index 0000000..2c3ef99
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/MyStringContext.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+public class MyStringContext {
+ private String myStringState = "string";
+
+ public String getMyStringState() {
+ return myStringState;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/context/OneInstanceAndOneStaticFieldOfSameTypeContext.java b/reflect/src/test/java/org/powermock/reflect/context/OneInstanceAndOneStaticFieldOfSameTypeContext.java
new file mode 100644
index 0000000..fc2e7c6
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/context/OneInstanceAndOneStaticFieldOfSameTypeContext.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.context;
+
+public class OneInstanceAndOneStaticFieldOfSameTypeContext {
+
+ private String myStringState = "myString";
+
+ private static String myStaticStringState = "21L";
+
+ public String getMyStringState() {
+ return myStringState;
+ }
+
+ public static String getMyStaticStringState() {
+ return myStaticStringState;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/internal/WhiteboxImplTest.java b/reflect/src/test/java/org/powermock/reflect/internal/WhiteboxImplTest.java
new file mode 100644
index 0000000..37cff8a
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/internal/WhiteboxImplTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.internal;
+
+import org.junit.Test;
+import org.junit.matchers.JUnitMatchers;
+import org.powermock.reflect.testclasses.Child;
+import org.powermock.reflect.testclasses.ClassWithOverloadedMethods;
+import org.powermock.reflect.testclasses.ClassWithStandardMethod;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+import static org.junit.matchers.JUnitMatchers.hasItem;
+
+/**
+ * Unit tests specific to the WhiteboxImpl.
+ */
+public class WhiteboxImplTest {
+
+ /**
+ * Asserts that a previous bug was fixed.
+ */
+ @Test
+ public void assertThatClassAndNotStringIsNotSameWhenInvokingCheckIfTypesAreSame() throws Exception {
+ Method method = WhiteboxImpl.getMethod(WhiteboxImpl.class, "checkIfParameterTypesAreSame", boolean.class,
+ Class[].class, Class[].class);
+ boolean invokeMethod = (Boolean) method.invoke(WhiteboxImpl.class, false, new Class<?>[] { Class.class },
+ new Class<?>[] { String.class });
+ assertFalse(invokeMethod);
+ }
+
+ @Test
+ public void assertThatClassAndClassIsSameWhenInvokingCheckIfTypesAreSame() throws Exception {
+ Method method = WhiteboxImpl.getMethod(WhiteboxImpl.class, "checkIfParameterTypesAreSame", boolean.class,
+ Class[].class, Class[].class);
+ boolean invokeMethod = (Boolean) method.invoke(WhiteboxImpl.class, false, new Class<?>[] { Class.class },
+ new Class<?>[] { Class.class });
+ assertTrue(invokeMethod);
+ }
+
+ @Test
+ public void getBestCandidateMethodReturnsMatchingMethodWhenNoOverloading() throws Exception {
+ final Method expectedMethod = ClassWithStandardMethod.class.getDeclaredMethod("myMethod", double.class);
+ final Method actualMethod = WhiteboxImpl.getBestMethodCandidate(ClassWithStandardMethod.class, "myMethod",
+ new Class<?>[] { double.class }, false);
+ assertEquals(expectedMethod, actualMethod);
+ }
+
+ @Test
+ public void getBestCandidateMethodReturnsMatchingMethodWhenOverloading() throws Exception {
+ final Method expectedMethod = ClassWithOverloadedMethods.class.getDeclaredMethod("overloaded", double.class,
+ Child.class);
+ final Method actualMethod = WhiteboxImpl.getBestMethodCandidate(ClassWithOverloadedMethods.class, "overloaded",
+ new Class<?>[] { double.class, Child.class }, false);
+ assertEquals(expectedMethod, actualMethod);
+ }
+
+ @Test
+ public void defaultMethodsAreFound() throws Exception {
+ assumeTrue(Float.valueOf(System.getProperty("java.specification.version")) >= 1.8f);
+
+ Method[] methods = WhiteboxImpl.getAllMethods(Collection.class);
+ List<String> methodNames = new ArrayList<String>();
+ for (Method method : methods) {
+ methodNames.add(method.getName());
+ }
+
+ assertThat(methodNames, hasItem("stream"));
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/AbstractClass.java b/reflect/src/test/java/org/powermock/reflect/testclasses/AbstractClass.java
new file mode 100644
index 0000000..a68a650
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/AbstractClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public abstract class AbstractClass {
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/AnInterface.java b/reflect/src/test/java/org/powermock/reflect/testclasses/AnInterface.java
new file mode 100644
index 0000000..98cde3b
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/AnInterface.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public interface AnInterface {
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/Child.java b/reflect/src/test/java/org/powermock/reflect/testclasses/Child.java
new file mode 100644
index 0000000..0ea87db
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/Child.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class Child extends Parent {
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithAMethod.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithAMethod.java
new file mode 100644
index 0000000..acb61a4
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithAMethod.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+import java.sql.Connection;
+
+public class ClassWithAMethod {
+
+ public void connect(Connection connection) {
+ if(connection == null) {
+ throw new IllegalArgumentException("param was null");
+ }
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithChildThatHasInternalState.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithChildThatHasInternalState.java
new file mode 100644
index 0000000..5f7437c
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithChildThatHasInternalState.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+ at SuppressWarnings("unused")
+public class ClassWithChildThatHasInternalState extends ClassWithInternalState {
+
+ private int anotherInternalState = 42;
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInterfaceConstructors.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInterfaceConstructors.java
new file mode 100644
index 0000000..a228979
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInterfaceConstructors.java
@@ -0,0 +1,31 @@
+package org.powermock.reflect.testclasses;
+
+/**
+ *
+ */
+public class ClassWithInterfaceConstructors {
+
+
+ private final ConstructorInterface constructorInterface;
+
+ public ClassWithInterfaceConstructors(ConstructorInterface constructorInterface) {this.constructorInterface = constructorInterface;}
+
+ public String getValue() {
+ return constructorInterface.getValue();
+ }
+
+ public interface ConstructorInterface {
+ String getValue();
+ }
+
+ public static class ConstructorInterfaceImpl implements ConstructorInterface {
+ private final String value;
+
+ public ConstructorInterfaceImpl(String value) {this.value = value;}
+
+ @Override
+ public String getValue() {
+ return value;
+ }
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInternalState.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInternalState.java
new file mode 100644
index 0000000..976ba09
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithInternalState.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ClassWithInternalState {
+
+ private static int staticState = 5;
+
+ private static final int staticFinalState = 15;
+
+ private int internalState = 0;
+
+ private int anotherInternalState = -1;
+
+ private final String finalString = "hello";
+
+ private long internalLongState = 17;
+
+ private String[] stringArray = new String[0];
+
+ private Set<String> genericState = new HashSet<String>();
+
+ private ClassWithPrivateMethods classWithPrivateMethods;
+
+ public String getFinalString() {
+ return finalString;
+ }
+
+ public void increaseInteralState() {
+ internalState++;
+ }
+
+ public void decreaseInteralState() {
+ internalState--;
+ }
+
+ public int getAnotherInternalState() {
+ return anotherInternalState;
+ }
+
+ public static int getStaticState() {
+ return staticState;
+ }
+
+ public static int getStaticFinalState() {
+ return staticFinalState;
+ }
+
+ public ClassWithPrivateMethods getClassWithPrivateMethods() {
+ return classWithPrivateMethods;
+ }
+
+ public long getInternalLongState() {
+ return internalLongState;
+ }
+
+ public Set<String> getGenericState() {
+ return genericState;
+ }
+
+ public static String methodWithArgument(InputStream inputStream) {
+ return "";
+ }
+
+ public String[] getStringArray() {
+ return stringArray;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithList.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithList.java
new file mode 100644
index 0000000..7b399db
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithList.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class ClassWithList {
+
+ @SuppressWarnings("unused")
+ private List<String> list = new LinkedList<String>();
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithMethodUsingSuperTypeArgument.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithMethodUsingSuperTypeArgument.java
new file mode 100644
index 0000000..59e2965
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithMethodUsingSuperTypeArgument.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class ClassWithMethodUsingSuperTypeArgument {
+ public void methodHavingASuperTypeArgument(ClassWithStandardMethod arg) {
+
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithObjectConstructors.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithObjectConstructors.java
new file mode 100644
index 0000000..6f2051b
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithObjectConstructors.java
@@ -0,0 +1,19 @@
+package org.powermock.reflect.testclasses;
+
+/**
+ *
+ */
+public class ClassWithObjectConstructors {
+
+ private final Object name;
+
+ protected ClassWithObjectConstructors(Object name) {
+
+ this.name = name;
+ }
+
+ public Object getName() {
+ return name;
+ }
+
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedConstructors.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedConstructors.java
new file mode 100644
index 0000000..f5a972e
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedConstructors.java
@@ -0,0 +1,39 @@
+package org.powermock.reflect.testclasses;
+
+/**
+ *
+ */
+public class ClassWithOverloadedConstructors {
+
+ private final String name;
+ private final boolean bool;
+ private final boolean bool1;
+
+ protected ClassWithOverloadedConstructors(String name) {
+
+ this(name, false, false);
+ }
+
+
+ protected ClassWithOverloadedConstructors(boolean bool, String name) {
+ this(name, bool, false);
+ }
+
+ protected ClassWithOverloadedConstructors(String name, boolean bool, boolean bool1) {
+ this.name = name;
+ this.bool = bool;
+ this.bool1 = bool1;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public boolean isBool() {
+ return bool;
+ }
+
+ public boolean isBool1() {
+ return bool1;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedMethods.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedMethods.java
new file mode 100644
index 0000000..230b400
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverloadedMethods.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class ClassWithOverloadedMethods {
+
+ public String overloaded(double value, Parent parent) {
+ return "parent";
+ }
+
+ public String overloaded(double value, Child child) {
+ return "child";
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverriddenMethod.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverriddenMethod.java
new file mode 100644
index 0000000..a6064e3
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithOverriddenMethod.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class ClassWithOverriddenMethod extends ClassWithStandardMethod {
+
+ @Override
+ public boolean myMethod(double value) {
+ return true;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrimitiveConstructors.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrimitiveConstructors.java
new file mode 100644
index 0000000..848780b
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrimitiveConstructors.java
@@ -0,0 +1,18 @@
+package org.powermock.reflect.testclasses;
+
+/**
+ *
+ */
+public class ClassWithPrimitiveConstructors {
+
+ private final long value;
+
+ public ClassWithPrimitiveConstructors(long value){
+
+ this.value = value;
+ }
+
+ public long getValue() {
+ return value;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrivateMethods.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrivateMethods.java
new file mode 100644
index 0000000..f0e5e3d
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithPrivateMethods.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+ at SuppressWarnings("unused")
+public class ClassWithPrivateMethods {
+
+ private boolean primitiveMethod(double value) {
+ return true;
+ }
+
+ private boolean wrappedMethod(Double value) {
+ return true;
+ }
+
+ private String methodWithPrimitiveIntAndString(int myInt, String aString) {
+ return aString + Integer.toString(myInt);
+ }
+
+ private int methodWithPrimitiveAndWrappedInt(int myInt, Integer myInt2) {
+ return myInt + myInt2;
+ }
+
+ private String evilConcatOfStrings(String[] strings) {
+ String returnValue = "";
+ for (String string : strings) {
+ returnValue += string;
+ }
+ return returnValue;
+ }
+
+ private int varArgsMethod(int... ints) {
+ int sum = 0;
+ for (int i : ints) {
+ sum += i;
+ }
+ return sum;
+ }
+
+ private ClassWithInternalState methodWithObjectArgument(ClassWithInternalState c) {
+ return c;
+ }
+
+ private Class<? super ClassWithInternalState> methodWithClassArgument(Class<? super ClassWithInternalState> c) {
+ return c;
+ }
+
+ private int varArgsMethod(int value) {
+ return value * 2;
+ }
+
+ private int varArgsMethod2(int value, int... moreValues) {
+ return value * 2 + moreValues.length;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSerializableState.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSerializableState.java
new file mode 100644
index 0000000..f8598f5
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSerializableState.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+import java.io.Serializable;
+
+ at SuppressWarnings("unused")
+public class ClassWithSerializableState {
+
+ private Serializable serializable;
+
+ private Object[] objectArray;
+
+ public void setSerializable(Serializable serializable) {
+ this.serializable = serializable;
+ }
+
+ public void setObjectArray(Object[] objectArray) {
+ this.objectArray = objectArray;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameName.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameName.java
new file mode 100644
index 0000000..52817a6
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameName.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class ClassWithSeveralMethodsWithSameName {
+
+ public double getDouble(double value) {
+ return value;
+ }
+
+ public double getDouble(double value1, double value2) {
+ return value1 + value2;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameNameOneWithoutParameters.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameNameOneWithoutParameters.java
new file mode 100644
index 0000000..13552ab
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSeveralMethodsWithSameNameOneWithoutParameters.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class ClassWithSeveralMethodsWithSameNameOneWithoutParameters {
+
+ public double getDouble() {
+ return Double.MAX_VALUE;
+ }
+
+ public double getDouble(double value) {
+ return value;
+ }
+
+ public double getDouble(double value1, double value2) {
+ return value1 + value2;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleInternalState.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleInternalState.java
new file mode 100644
index 0000000..78dc073
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleInternalState.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithSimpleInternalState {
+
+ private int someIntState = -1;
+
+ private String someStringState = "-1";
+
+ private static long someStaticLongState = -1L;
+
+ public static long getLong() {
+ return someStaticLongState;
+ }
+
+ public long getSomeStaticLongState() {
+ return someStaticLongState;
+ }
+
+ public int getSomeIntState() {
+ return someIntState;
+ }
+
+ public String getSomeStringState() {
+ return someStringState;
+ }
+
+ public static void setLong(long state) {
+ someStaticLongState = state;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleStateOfSameType.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleStateOfSameType.java
new file mode 100644
index 0000000..7b0f075
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithSimpleStateOfSameType.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithSimpleStateOfSameType {
+
+ private String someStringState = "-1";
+ private String someOtherStringState = "-1";
+
+ public String getSomeStringState() {
+ return someStringState;
+ }
+
+ public String getSomeOtherStringState() {
+ return someOtherStringState;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStandardMethod.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStandardMethod.java
new file mode 100644
index 0000000..4f0903c
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStandardMethod.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithStandardMethod {
+
+ public boolean myMethod(double value) {
+ return true;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticAndInstanceInternalStateOfSameType.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticAndInstanceInternalStateOfSameType.java
new file mode 100644
index 0000000..267064e
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticAndInstanceInternalStateOfSameType.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithStaticAndInstanceInternalStateOfSameType {
+
+ private String stringState = "String state";
+
+ private static String staticStringState = "Static String state";
+
+ public String getStaticStringState() {
+ return staticStringState;
+ }
+
+ public String getStringState() {
+ return stringState;
+ }
+
+ public static void reset() {
+ staticStringState = "Static String state";
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticMethod.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticMethod.java
new file mode 100644
index 0000000..582612f
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithStaticMethod.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithStaticMethod {
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ private static String aStaticMethod(byte[] something) {
+ return "hello";
+ }
+
+ @SuppressWarnings({"UnusedDeclaration"})
+ private static String anotherStaticMethod(Object object, byte[] something) {
+ return object+" "+something;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithUniquePrivateMethods.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithUniquePrivateMethods.java
new file mode 100644
index 0000000..28febb2
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithUniquePrivateMethods.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+ at SuppressWarnings("unused")
+public class ClassWithUniquePrivateMethods {
+
+ private boolean primitiveMethodWithOnlyOneArgument(double value) {
+ return true;
+ }
+
+ private static boolean primitiveStaticMethodWithOnlyOneArgument(double value) {
+ return true;
+ }
+
+ private boolean primitiveMethod(double value, double value2) {
+ return true;
+ }
+
+ private Object twoArgs(double value, double value2, Object obj) {
+ return new Object();
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor.java
new file mode 100644
index 0000000..c13aea4
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithVarArgsConstructor {
+
+
+ private final String[] strings;
+
+ private ClassWithVarArgsConstructor(String...strings) {
+ this.strings = strings;
+ }
+
+ public String[] getStrings() {
+ return strings;
+ }
+}
+
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor2.java b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor2.java
new file mode 100644
index 0000000..301ca66
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/ClassWithVarArgsConstructor2.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.powermock.reflect.testclasses;
+
+public class ClassWithVarArgsConstructor2 {
+
+ private final String[] strings;
+
+ private ClassWithVarArgsConstructor2(String required, String... strings) {
+ this.strings = new String[strings.length + 1];
+ this.strings[0] = required;
+ System.arraycopy(strings, 0, this.strings, 1, strings.length);
+ }
+
+ public String[] getStrings() {
+ return strings;
+ }
+}
diff --git a/reflect/src/test/java/org/powermock/reflect/testclasses/Parent.java b/reflect/src/test/java/org/powermock/reflect/testclasses/Parent.java
new file mode 100644
index 0000000..499b82d
--- /dev/null
+++ b/reflect/src/test/java/org/powermock/reflect/testclasses/Parent.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.powermock.reflect.testclasses;
+
+public class Parent {
+
+}
diff --git a/release/easymock-extension-api-full/pom.xml b/release/easymock-extension-api-full/pom.xml
new file mode 100644
index 0000000..40be029
--- /dev/null
+++ b/release/easymock-extension-api-full/pom.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-easymock-release-full</artifactId>
+ <packaging>pom</packaging>
+ <name>powermock-easymock-single-jar-release-full</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, EasyMock and all test framework modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Sources -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-easymock-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/easymock-extension-api-full/src/assembly/full.xml b/release/easymock-extension-api-full/src/assembly/full.xml
new file mode 100644
index 0000000..14cd0ba
--- /dev/null
+++ b/release/easymock-extension-api-full/src/assembly/full.xml
@@ -0,0 +1,15 @@
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/junit-without-mock-framework/pom.xml b/release/junit-without-mock-framework/pom.xml
new file mode 100644
index 0000000..b18999b
--- /dev/null
+++ b/release/junit-without-mock-framework/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-junit-without-mock-framework</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core and JUnit module.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-without-test-and-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-junit-without-mock-framework-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/junit-without-mock-framework/src/assembly/full.xml b/release/junit-without-mock-framework/src/assembly/full.xml
new file mode 100644
index 0000000..14cd0ba
--- /dev/null
+++ b/release/junit-without-mock-framework/src/assembly/full.xml
@@ -0,0 +1,15 @@
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/mockito-extension-api-full/pom.xml b/release/mockito-extension-api-full/pom.xml
new file mode 100644
index 0000000..f73ffde
--- /dev/null
+++ b/release/mockito-extension-api-full/pom.xml
@@ -0,0 +1,162 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-mockito-release-full</artifactId>
+ <packaging>pom</packaging>
+ <name>powermock-mockito-single-jar-release-full</name>
+
+ <description>
+ Single jar containing source and binaries for PowerMock core and all modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Sources -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/mockito-extension-api-full/src/assembly/full.xml b/release/mockito-extension-api-full/src/assembly/full.xml
new file mode 100644
index 0000000..14cd0ba
--- /dev/null
+++ b/release/mockito-extension-api-full/src/assembly/full.xml
@@ -0,0 +1,15 @@
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/mockito2-extension-api-full/pom.xml b/release/mockito2-extension-api-full/pom.xml
new file mode 100644
index 0000000..759b5e0
--- /dev/null
+++ b/release/mockito2-extension-api-full/pom.xml
@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-mockito2-release-full</artifactId>
+ <packaging>pom</packaging>
+ <name>powermock-mockito2-single-jar-release-full</name>
+
+ <description>
+ Single jar containing source and binaries for PowerMock core and all modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Sources -->
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-common</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4-legacy</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit3</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ <classifier>sources</classifier>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito2-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/mockito2-extension-api-full/src/assembly/full.xml b/release/mockito2-extension-api-full/src/assembly/full.xml
new file mode 100644
index 0000000..41941a4
--- /dev/null
+++ b/release/mockito2-extension-api-full/src/assembly/full.xml
@@ -0,0 +1,33 @@
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/pom.xml b/release/pom.xml
new file mode 100644
index 0000000..a8e7fed
--- /dev/null
+++ b/release/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Copyright 2010 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>powermock-release</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Convenience distributions containing various combinations of modules.
+ </description>
+
+ <modules>
+ <module>easymock-extension-api-full</module>
+ <module>with-junit-easymock-dependencies</module>
+ <module>with-testng-easymock-dependencies</module>
+ <module>junit-without-mock-framework</module>
+ <module>testng-without-mock-framework</module>
+ <module>without-test-and-mock-framework</module>
+ <module>mockito-extension-api-full</module>
+ <module>with-junit-mockito-dependencies</module>
+ <module>with-testng-mockito-dependencies</module>
+ <module>mockito2-extension-api-full</module>
+ <module>with-junit-mockito2-dependencies</module>
+ <module>with-testng-mockito2-dependencies</module>
+ </modules>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>2.5.3</version>
+ <executions>
+ <execution>
+ <!--Suppressing execution. OSGI Manifests are not needed for "packaged" releases. OSGI users will take the features instead -->
+ <id>bundle-manifest</id>
+ <phase>none</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/testng-without-mock-framework/pom.xml b/release/testng-without-mock-framework/pom.xml
new file mode 100644
index 0000000..9844c5d
--- /dev/null
+++ b/release/testng-without-mock-framework/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-testng-without-mock-framework</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core and TestNG module.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-without-test-and-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-testng-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-testng-without-mock-framework-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/testng-without-mock-framework/src/assembly/full.xml b/release/testng-without-mock-framework/src/assembly/full.xml
new file mode 100644
index 0000000..14cd0ba
--- /dev/null
+++ b/release/testng-without-mock-framework/src/assembly/full.xml
@@ -0,0 +1,15 @@
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-junit-easymock-dependencies/pom.xml b/release/with-junit-easymock-dependencies/pom.xml
new file mode 100644
index 0000000..4d4f44d
--- /dev/null
+++ b/release/with-junit-easymock-dependencies/pom.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-junit-easymock-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, JUnit and EasyMock modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-junit-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-easymock-junit-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-junit-easymock-dependencies/src/assembly/final.xml b/release/with-junit-easymock-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..267bc77
--- /dev/null
+++ b/release/with-junit-easymock-dependencies/src/assembly/final.xml
@@ -0,0 +1,12 @@
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-junit-mockito-dependencies/pom.xml b/release/with-junit-mockito-dependencies/pom.xml
new file mode 100644
index 0000000..ac215c4
--- /dev/null
+++ b/release/with-junit-mockito-dependencies/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-junit-mockito-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, JUnit and Mockito modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-junit-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito-junit-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-junit-mockito-dependencies/src/assembly/final.xml b/release/with-junit-mockito-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..267bc77
--- /dev/null
+++ b/release/with-junit-mockito-dependencies/src/assembly/final.xml
@@ -0,0 +1,12 @@
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-junit-mockito2-dependencies/pom.xml b/release/with-junit-mockito2-dependencies/pom.xml
new file mode 100644
index 0000000..699548c
--- /dev/null
+++ b/release/with-junit-mockito2-dependencies/pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-junit-mockito2-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, JUnit and Mockito 2 modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-junit-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito2.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito2-junit-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-junit-mockito2-dependencies/src/assembly/final.xml b/release/with-junit-mockito2-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..b90cf70
--- /dev/null
+++ b/release/with-junit-mockito2-dependencies/src/assembly/final.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-testng-easymock-dependencies/pom.xml b/release/with-testng-easymock-dependencies/pom.xml
new file mode 100644
index 0000000..c77c001
--- /dev/null
+++ b/release/with-testng-easymock-dependencies/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-testng-easymock-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, TestNG and EasyMock modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-testng-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-easymock-testng-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-testng-easymock-dependencies/src/assembly/final.xml b/release/with-testng-easymock-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..267bc77
--- /dev/null
+++ b/release/with-testng-easymock-dependencies/src/assembly/final.xml
@@ -0,0 +1,12 @@
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-testng-mockito-dependencies/pom.xml b/release/with-testng-mockito-dependencies/pom.xml
new file mode 100644
index 0000000..550a87f
--- /dev/null
+++ b/release/with-testng-mockito-dependencies/pom.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-testng-mockito-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, TestNG and Mockito modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-testng-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito1.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito-testng-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-testng-mockito-dependencies/src/assembly/final.xml b/release/with-testng-mockito-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..267bc77
--- /dev/null
+++ b/release/with-testng-mockito-dependencies/src/assembly/final.xml
@@ -0,0 +1,12 @@
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/with-testng-mockito2-dependencies/pom.xml b/release/with-testng-mockito2-dependencies/pom.xml
new file mode 100644
index 0000000..cd4a3e9
--- /dev/null
+++ b/release/with-testng-mockito2-dependencies/pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-with-testng-mockito2-dependencies</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, TestNG and Mockito 2 modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-release-testng-without-mock-framework</artifactId>
+ <type>pom</type>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>${mockito2.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-mockito2-testng-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/final.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/with-testng-mockito2-dependencies/src/assembly/final.xml b/release/with-testng-mockito2-dependencies/src/assembly/final.xml
new file mode 100644
index 0000000..b90cf70
--- /dev/null
+++ b/release/with-testng-mockito2-dependencies/src/assembly/final.xml
@@ -0,0 +1,30 @@
+<!--
+ ~ /*
+ ~ * Copyright 2016 the original author or authors.
+ ~ *
+ ~ * Licensed under the Apache License, Version 2.0 (the "License");
+ ~ * you may not use this file except in compliance with the License.
+ ~ * You may obtain a copy of the License at
+ ~ *
+ ~ * http://www.apache.org/licenses/LICENSE-2.0
+ ~ *
+ ~ * Unless required by applicable law or agreed to in writing, software
+ ~ * distributed under the License is distributed on an "AS IS" BASIS,
+ ~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ * See the License for the specific language governing permissions and
+ ~ * limitations under the License.
+ ~
+ -->
+
+<assembly>
+ <formats>
+ <format>zip</format>
+ </formats>
+ <includeBaseDirectory>true</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <unpack>false</unpack>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/release/without-test-and-mock-framework/pom.xml b/release/without-test-and-mock-framework/pom.xml
new file mode 100644
index 0000000..3b300e2
--- /dev/null
+++ b/release/without-test-and-mock-framework/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5-SNAPSHOT</version>
+ <relativePath>../../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>powermock-release-without-test-and-mock-framework</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Single jar containing binaries for PowerMock core, without any test or mock frameworks.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-reflect</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-support</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-classloading-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <configuration>
+ <finalName>powermock-without-test-and-mock-framework-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/full.xml</descriptor>
+ </descriptors>
+ </configuration>
+ <executions>
+ <execution>
+ <id>make-assembly</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attached</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/release/without-test-and-mock-framework/src/assembly/full.xml b/release/without-test-and-mock-framework/src/assembly/full.xml
new file mode 100644
index 0000000..14cd0ba
--- /dev/null
+++ b/release/without-test-and-mock-framework/src/assembly/full.xml
@@ -0,0 +1,15 @@
+<assembly>
+ <id>full</id>
+ <formats>
+ <format>jar</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory></outputDirectory>
+ <outputFileNameMapping></outputFileNameMapping>
+ <unpack>true</unpack>
+ <useTransitiveDependencies>false</useTransitiveDependencies>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/src/site/apt/docs/gettingStarted.apt b/src/site/apt/docs/gettingStarted.apt
new file mode 100644
index 0000000..faa657a
--- /dev/null
+++ b/src/site/apt/docs/gettingStarted.apt
@@ -0,0 +1,40 @@
+ ------------------------------
+ Getting started with PowerMock
+ ------------------------------
+
+Usage
+
+ Add the following to your pom.xml:
+
++--------------------------------------------------------------------+
+<dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>0.5</version>
+ <scope>test</scope>
+</dependency>
+<dependency>
+ <groupId>org.powermock.modules</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>0.5</version>
+ <scope>test</scope>
+</dependency>
+<dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymockclassextension</artifactId>
+ <version>2.2.2</version>
+ <scope>test</scope>
+</dependency>
++--------------------------------------------------------------------+
+
+ Write a test like this:
+
++--------------------------------------------------------------------+
+ at RunWith(PowerMockRunner.class)
+ at PrepareForTest( { YourClassWitEgStaticMethod.class })
+public class YourTestCase {
+...
+}
++--------------------------------------------------------------------+
+
+ Please refer to the example projects for JUnit 3 samples.
diff --git a/src/site/apt/docs/installing.apt b/src/site/apt/docs/installing.apt
new file mode 100644
index 0000000..3856ef6
--- /dev/null
+++ b/src/site/apt/docs/installing.apt
@@ -0,0 +1,24 @@
+ ------------------------------
+ Installing
+ ------------------------------
+
+Binary release
+
+ Not yet available...
+
+Installing from the trunk
+
++----------------------------------------------------------------------------------+
+svn checkout https://powermock.svn.sourceforge.net/svnroot/powermock/trunk powermock
+cd powermock
+mvn install
++----------------------------------------------------------------------------------+
+
+Installing a specific version
+
++----------------------------------------------------------------------------------------------------------------+
+svn checkout https://powermock.svn.sourceforge.net/svnroot/powermock/tags/powermock-${version} powermock-${version}
+cd powermock-${version}
+mvn install
++----------------------------------------------------------------------------------------------------------------+
+ Note: Replace ${version} with the version number, such as 0.5.
diff --git a/src/site/apt/docs/motivation.apt b/src/site/apt/docs/motivation.apt
new file mode 100644
index 0000000..ad9e6d9
--- /dev/null
+++ b/src/site/apt/docs/motivation.apt
@@ -0,0 +1,130 @@
+ ------------------------------
+ Motivation
+ ------------------------------
+
+Motivation and example
+
+ PowerMock is a Java mock framework that can be used to solve testing problems that is normally concidered difficult or even impossible to test. For instance it is possible to mock static methods, remove static initializers, allow mocking without dependency injection and more. PowerMock can do all of these tricks by modifying the byte-code at run-time when the tests are being exececuted. PowerMock also contains some utilities that gives you easier access to an objects internal state.
+
+ For PowerMock to know which classes to manipulate to allow for improved testability, you need to specify this using an annotation called @PrepareForTest. The test must also be executed using one of PowerMock's JUnit runners.
+
+ A pretty common use-case of when to use PowerMock is when your code is calling a static method, for example to get an instance from a factory. For example:
+
++--------------------------------------------------------------------+
+ public class MyServiceUser {
+
+ public int getNumberOfPersons() {
+ MyService myService = DependencyManager.getInstance().getMyService();
+ Set<Person> allPersons = myService.getAllPersons();
+ return allPersons.size();
+ }
+
+ ..
+ }
++--------------------------------------------------------------------+
+
+ The problem with this code is that without byte-code manipulation the DependencyManager.getInstance() (which is a static method) cannot be mocked. There are of course numerous ways to get around this,
+ for example you could refactor the code and use dependency injection of the MyService instance. But why should you have to refactor your existing code ONLY for the sake of testability?
+ PowerMock will provide you with the choice of deciding yourself. In several projects a common approach to make the previous code testable is to wrap the call to the static method to an instance method like this:
+
++--------------------------------------------------------------------+
+ public class MyServiceUser {
+
+ public int getNumberOfPersons() {
+ MyService myService = getDependencyManagerInstance().getMyService();
+ Set<Person> allPersons = myService.getAllPersons();
+ return allPersons.size();
+ }
+
+ protected DependencyManager getDependencyManagerInstance() {
+ return DependencyManager.getInstance();
+ }
+ ..
+ }
++--------------------------------------------------------------------+
+
+ Doing so will allow for partial mocking, i.e. the call to getDependencyManagerInstance() can be mocked in the test class itself and return a mock implementation of the DependencyManager instead of ever calling the static getInstance() method. An example test for this method may look like this using standard EasyMock (PowerMock has some utility methods that makes it easier to take advantage of partial mocking but those are not shown here):
+
++--------------------------------------------------------------------+
+ public class MyServiceUserTest {
+
+ @Test
+ public void testGetNumberOfPersons() {
+ // We extract the method using reflection
+ Method getDependencyManagerInstanceMethod = MyServiceUser.class.getMethod("getDependencyManagerInstance");
+
+ DependencyManager dependencyManagerMock = createMock(DependencyManager.class);
+ MyService myServiceMock = createMock(MyService.class);
+
+ // Create a partial mock object for the MyServiceUser, in this case only mock the getDependencyManagerInstance method.
+ MyServiceUser tested = createMock(MyServiceUser.class, new Method[] { getDependencyManagerInstanceMethod } );
+
+ expect(tested.getDependencyManagerInstance()).andReturn(dependencyManagerMock);
+ expect(dependencyManagerMock.getMyService()).andReturn(myServiceMock);
+
+ Set<Person> personSetMock = new HashSet<String>();
+ personSetMock.put(new Person());
+
+ final int expectedNUmberOfPersons = 1;
+
+ replay(dependencyManagerMock, myServiceMock, tested);
+
+ // perform the actual test
+ int actualNumberOfPersons = tested.getNumberOfPersons();
+
+ verify(dependencyManagerMock, myServiceMock, tested);
+
+ assertEquals(expectedNUmberOfPersons, actualNumberOfPersons);
+ }
+ }
++--------------------------------------------------------------------+
+
+ But extracting the call to the static method to an instance method just for the sake of testability is a bad thing. Why should we write worse production code just to make it unit testable? By using PowerMock we can now test the original code without making any changes to it what so ever. Here's the code for doing so using JUnit 4:
+
++--------------------------------------------------------------------+
+ @RunWith(PowerMockRunner.class)
+ @PrepareForTest(DependencyManager.class)
+ public class MyServiceUserTest {
+
+ @Test
+ public void testGetNumberOfPersons() {
+ // Notice how we just instansiate the MyServiceUser class without any tricks
+ MyServiceUser tested = new MyServiceUser();
+
+ // Create the other mocks as usual
+ DependencyManager dependencyManagerMock = createMock(DependencyManager.class);
+ MyService myServiceMock = createMock(MyService.class);
+
+ // This is how to tell PowerMock to mock all static methods of the DependencyManager class
+ mockStatic(DependencyManager.class);
+
+ // This is how to setup the expectation for the static method call to DependencyManager.getInstance()
+ expect(DependencyManager.getInstance()).andReturn(dependencyManagerMock);
+
+ expect(dependencyManagerMock.getMyService()).andReturn(myServiceMock);
+
+ Set<Person> personSetMock = new HashSet<String>();
+ personSetMock.put(new Person());
+
+ final int expectedNUmberOfPersons = 1;
+
+ // Notice that also DependencyManager.class is replayed.
+ replay(dependencyManagerMock, myServiceMock, DependencyManager.class);
+
+ // perform the actual test
+ int actualNumberOfPersons = tested.getNumberOfPersons();
+
+ // Notice that also DependencyManager.class is verified.
+ verify(dependencyManagerMock, myServiceMock, DependencyManager.class);
+
+ assertEquals(expectedNUmberOfPersons, actualNumberOfPersons);
+ }
+ }
++--------------------------------------------------------------------+
+
+ Voila! Without changing our production code at all we were now able unit test the code. A few things may need to be explained. First of all the @PrepareForTest annotation should necessarily (but can and should in cases when using partial mocking)
+ point to the class being tested. Instead the @PrepareForTest annotation contains the class(es) that encapsulates the logic that is normally not testable. In this case the DependencyManager.getInstance() is a static method which is called in code that
+ we want to test and thus we must add this class to the annotation. You can also supply several classes using @PrepareForTest(classes={ Class1.class, Class2.class, .., ClassN.class }). You can also supply the fully-qualified names of a class instead of the class type.
+ This is needed when suppressing static initializers but that is beyond the basics and will not be described here.
+
+ PowerMock contains tests for all its functionality. The best way to learn how to use PowerMock and what use cases it deals with is to look in the junit4 project (if you're using JUnit 4.4) or junit4-legacy (for JUnit 4.0 to 4.3) or junit3 (for JUnit 3.x). There you'' find a bunch of trivial examples that lets you explore the PowerMock API and features. The example code that we went through above is also available from subversion under the AbstractFactory project.
\ No newline at end of file
diff --git a/src/site/resources/images/logos/jayway.png b/src/site/resources/images/logos/jayway.png
new file mode 100644
index 0000000..e766350
Binary files /dev/null and b/src/site/resources/images/logos/jayway.png differ
diff --git a/src/site/resources/images/logos/powermock.png b/src/site/resources/images/logos/powermock.png
new file mode 100644
index 0000000..17026cc
Binary files /dev/null and b/src/site/resources/images/logos/powermock.png differ
diff --git a/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 0000000..ad6be9b
--- /dev/null
+++ b/src/site/site.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ ~ Copyright 2011 the original author or authors.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project name="PowerMock">
+ <publishDate position="left" format="yyyy-MM-dd" />
+ <bannerLeft>
+ <name>PowerMock</name>
+ <src>images/logos/powermock.png</src>
+ <href>http://powermock.org/</href>
+ </bannerLeft>
+ <bannerRight>
+ <src></src>
+ </bannerRight>
+ <body>
+ <links>
+ <item name="JUnit" href="http://junit.org/" />
+ <item name="EasyMock" href="http://easymock.org/" />
+ <item name="MockME" href="http://mockme.org/" />
+ </links>
+
+ <menu name="Overview">
+ <item name="Home" href="/" />
+ <item name="Google code" href="http://code.google.com/p/powermock/" />
+ <item name="Downloads" href="http://sourceforge.net/project/showfiles.php?group_id=224812" />
+ </menu>
+
+ <menu name="Documentation">
+ <item name="Gettng started" href="docs/gettingStarted.html" />
+ <item name="Installing" href="docs/installing.html" />
+ <item name="Motivation" href="docs/motivation.html" />
+ <item name="API" href="apidocs/index.html" /> </menu>
+
+ <menu ref="reports" name="Reports" />
+ </body>
+
+ <poweredBy>
+<!-- <logo name="Built by Bamboo"
+ href="http://www.atlassian.com/software/bamboo/"
+ img="images/logos/bamboo.png" />-->
+ <logo name="Build with Maven 2" href="http://maven.apache.org"
+ img="images/logos/maven-feather.png" />
+ <logo name="Sponsored by Jayway" href="http://www.jayway.com"
+ img="images/logos/jayway.png" />
+ </poweredBy>
+
+</project>
diff --git a/tests/pom.xml b/tests/pom.xml
new file mode 100644
index 0000000..c15b708
--- /dev/null
+++ b/tests/pom.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock</artifactId>
+ <version>1.6.5</version>
+ </parent>
+
+ <groupId>org.powermock.tests</groupId>
+ <artifactId>powermock-tests</artifactId>
+ <packaging>pom</packaging>
+ <name>${project.artifactId}</name>
+
+ <description>
+ Common tests for PowerMock core and modules for mocking frameworks.
+ </description>
+
+ <modules>
+ <module>utils</module>
+ </modules>
+</project>
diff --git a/tests/utils/pom.xml b/tests/utils/pom.xml
new file mode 100644
index 0000000..479cf36
--- /dev/null
+++ b/tests/utils/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>powermock-tests</artifactId>
+ <groupId>org.powermock.tests</groupId>
+ <version>1.6.5</version>
+ </parent>
+
+ <artifactId>powermock-tests-utils</artifactId>
+ <name>${project.artifactId}</name>
+ <url>http://www.powermock.org</url>
+
+ <description>
+ Common set of classes to test PowerMock features in mocking framework modules.
+ </description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>2.5</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <skip>true</skip>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/tests/utils/src/main/java/samples/Service.java b/tests/utils/src/main/java/samples/Service.java
new file mode 100644
index 0000000..54a7b5e
--- /dev/null
+++ b/tests/utils/src/main/java/samples/Service.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples;
+
+/**
+ * A very simple service interface used as a dependency for various classes to
+ * demonstrate different kinds of mocking.
+ *
+ * @author Johan Haleby
+ */
+public interface Service {
+
+ public String getServiceMessage();
+}
diff --git a/tests/utils/src/main/java/samples/abstractmocking/AbstractMethodMocking.java b/tests/utils/src/main/java/samples/abstractmocking/AbstractMethodMocking.java
new file mode 100644
index 0000000..9d4b0bd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/abstractmocking/AbstractMethodMocking.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.abstractmocking;
+
+/**
+ * Demonstrates that PowerMock can mock abstract methods. This was previously a
+ * bug in PowerMock.
+ */
+public abstract class AbstractMethodMocking {
+
+ public String getValue() {
+ return getIt();
+ }
+
+ protected abstract String getIt();
+
+}
diff --git a/tests/utils/src/main/java/samples/annotationbased/AnnotationDemo.java b/tests/utils/src/main/java/samples/annotationbased/AnnotationDemo.java
new file mode 100644
index 0000000..2a59077
--- /dev/null
+++ b/tests/utils/src/main/java/samples/annotationbased/AnnotationDemo.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.annotationbased;
+
+import samples.Service;
+
+public class AnnotationDemo {
+
+ private Service service;
+
+ public AnnotationDemo(Service service) {
+ this.service = service;
+ }
+
+ public AnnotationDemo() {
+
+ }
+
+ public String getServiceMessage() {
+ return service.getServiceMessage();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/anonymousmocking/MyAbstractClass.java b/tests/utils/src/main/java/samples/anonymousmocking/MyAbstractClass.java
new file mode 100644
index 0000000..5bce0d4
--- /dev/null
+++ b/tests/utils/src/main/java/samples/anonymousmocking/MyAbstractClass.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.anonymousmocking;
+
+public abstract class MyAbstractClass {
+ public abstract String getMessage();
+}
diff --git a/tests/utils/src/main/java/samples/anonymousmocking/StupidAnonymous.java b/tests/utils/src/main/java/samples/anonymousmocking/StupidAnonymous.java
new file mode 100644
index 0000000..0293184
--- /dev/null
+++ b/tests/utils/src/main/java/samples/anonymousmocking/StupidAnonymous.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.anonymousmocking;
+
+import samples.Service;
+
+public class StupidAnonymous {
+
+ // TODO We need to make sure that you also can mock private members from an
+ // inner class!
+ protected Service service;
+
+ public void setService(Service service) {
+ this.service = service;
+ }
+
+ public String getMessageFromMyClass() {
+
+ MyAbstractClass myclass = new MyAbstractClass() {
+ @Override
+ public String getMessage() {
+ return "Hello world!";
+ }
+ };
+
+ return myclass.getMessage();
+ }
+
+ public String getMessagesFromSeveralInnerClasses() {
+
+ MyAbstractClass myclass1 = new MyAbstractClass() {
+ @Override
+ public String getMessage() {
+ return "Hello world 1!";
+ }
+ };
+
+ MyAbstractClass myclass2 = new MyAbstractClass() {
+ @Override
+ public String getMessage() {
+ return "Hello world 2!";
+ }
+ };
+ return myclass1.getMessage() + " " + myclass2.getMessage();
+ }
+
+ public String getServiceMessageFromInnerClass() {
+
+ MyAbstractClass myclass = new MyAbstractClass() {
+ @Override
+ public String getMessage() {
+ return service.getServiceMessage();
+ }
+ };
+
+ return myclass.getMessage();
+ }
+
+ public String getMessageFromOtherMethodInInnerClass() {
+
+ MyAbstractClass myclass = new MyAbstractClass() {
+ @Override
+ public String getMessage() {
+ return returnThisMessage();
+ }
+
+ public String returnThisMessage() {
+ return "A message";
+ }
+ };
+
+ return myclass.getMessage();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/argumentmatcher/ArgumentMatcherDemo.java b/tests/utils/src/main/java/samples/argumentmatcher/ArgumentMatcherDemo.java
new file mode 100644
index 0000000..d896772
--- /dev/null
+++ b/tests/utils/src/main/java/samples/argumentmatcher/ArgumentMatcherDemo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.argumentmatcher;
+
+import java.util.List;
+
+public class ArgumentMatcherDemo {
+
+ public List<String> findByNamedQuery(String argument, List<String> someList) {
+ someList.add("one");
+ return someList;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/classhierarchy/ChildA.java b/tests/utils/src/main/java/samples/classhierarchy/ChildA.java
new file mode 100644
index 0000000..7c1943f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/classhierarchy/ChildA.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.classhierarchy;
+
+public class ChildA extends Parent {
+
+}
diff --git a/tests/utils/src/main/java/samples/classhierarchy/ChildB.java b/tests/utils/src/main/java/samples/classhierarchy/ChildB.java
new file mode 100644
index 0000000..6cbe682
--- /dev/null
+++ b/tests/utils/src/main/java/samples/classhierarchy/ChildB.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.classhierarchy;
+
+public class ChildB extends Parent {
+
+}
diff --git a/tests/utils/src/main/java/samples/classhierarchy/Parent.java b/tests/utils/src/main/java/samples/classhierarchy/Parent.java
new file mode 100644
index 0000000..058a8c5
--- /dev/null
+++ b/tests/utils/src/main/java/samples/classhierarchy/Parent.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.classhierarchy;
+
+public class Parent {
+ private int value;
+
+ public int getValue() {
+ return value;
+ }
+
+ public void setValue(int value) {
+ this.value = value;
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/classwithinnermembers/ClassWithInnerMembers.java b/tests/utils/src/main/java/samples/classwithinnermembers/ClassWithInnerMembers.java
new file mode 100644
index 0000000..a84b375
--- /dev/null
+++ b/tests/utils/src/main/java/samples/classwithinnermembers/ClassWithInnerMembers.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.classwithinnermembers;
+
+/**
+ * Class that is used to test that local and member class works with PowerMock.
+ */
+public class ClassWithInnerMembers {
+
+ private interface InnerInterface {
+ String doStuff();
+ }
+
+ private static class MyInnerClass implements InnerInterface {
+
+ @Override
+ public String doStuff() {
+ return "member class";
+ }
+ }
+
+ private static class StaticInnerClassWithConstructorArgument implements InnerInterface {
+
+ private final String value;
+
+ public StaticInnerClassWithConstructorArgument(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String doStuff() {
+ return value;
+ }
+ }
+
+ private class MyInnerClassWithConstructorArgument implements InnerInterface {
+
+ private final String value;
+
+ public MyInnerClassWithConstructorArgument(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String doStuff() {
+ return value;
+ }
+ }
+
+ public String getValue() {
+ return new MyInnerClass().doStuff();
+ }
+
+ public String getValueForInnerClassWithConstructorArgument() {
+ return new MyInnerClassWithConstructorArgument("value").doStuff();
+ }
+
+ public String getValueForStaticInnerClassWithConstructorArgument() {
+ return new StaticInnerClassWithConstructorArgument("value").doStuff();
+ }
+
+ public String getLocalClassValue() {
+ class MyLocalClass implements InnerInterface {
+ @Override
+ public String doStuff() {
+ return "local class";
+ }
+ }
+
+ return new MyLocalClass().doStuff();
+ }
+
+ public String getLocalClassValueWithArgument() {
+ class MyLocalClass implements InnerInterface {
+
+ private final String value;
+
+ public MyLocalClass(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public String doStuff() {
+ return value;
+ }
+ }
+
+ return new MyLocalClass("my value").doStuff();
+ }
+
+ public String getValueForAnonymousInnerClass() {
+
+ InnerInterface inner = new InnerInterface() {
+ @Override
+ public String doStuff() {
+ return "value";
+ }
+ };
+
+ return inner.doStuff();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/constructor/PrivateConstructorDemo.java b/tests/utils/src/main/java/samples/constructor/PrivateConstructorDemo.java
new file mode 100644
index 0000000..586bec3
--- /dev/null
+++ b/tests/utils/src/main/java/samples/constructor/PrivateConstructorDemo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.constructor;
+
+import samples.Service;
+
+/**
+ * Demonstrates the ability to invoke a test on a private constructor as well as
+ * lazy initialization of private collaborators.
+ *
+ * @author Johan Haleby
+ */
+public class PrivateConstructorDemo {
+
+ private Service privateService;
+
+ private String constructorResult;
+
+ private PrivateConstructorDemo(String completeName) {
+ constructorResult = privateService.getServiceMessage() + completeName;
+ }
+
+ public String getConstructorResult() {
+ return constructorResult;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/constructor/PrivateConstructorInstantiationDemo.java b/tests/utils/src/main/java/samples/constructor/PrivateConstructorInstantiationDemo.java
new file mode 100644
index 0000000..47250ca
--- /dev/null
+++ b/tests/utils/src/main/java/samples/constructor/PrivateConstructorInstantiationDemo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.constructor;
+
+/**
+ * Class used to demonstrate the private constructor instantiation.
+ *
+ * @author Johan Haleby
+ */
+public class PrivateConstructorInstantiationDemo {
+
+ private final int state;
+
+ private PrivateConstructorInstantiationDemo() {
+ this(42);
+ }
+
+ private PrivateConstructorInstantiationDemo(int state) {
+ this.state = state;
+ }
+
+ public int getState() {
+ return state;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/constructor/PublicConstructorDemo.java b/tests/utils/src/main/java/samples/constructor/PublicConstructorDemo.java
new file mode 100644
index 0000000..4919f6d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/constructor/PublicConstructorDemo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.constructor;
+
+import samples.Service;
+
+/**
+ * Demonstrates the ability to invoke a test on a private constructor as well as
+ * lazy initialization of private collaborators.
+ *
+ * @author Johan Haleby
+ */
+public class PublicConstructorDemo {
+
+ private Service privateService;
+
+ private String constructorResult;
+
+ public PublicConstructorDemo(String completeName) {
+ constructorResult = privateService.getServiceMessage() + completeName;
+ }
+
+ public String getConstructorResult() {
+ return constructorResult;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/constructor/PublicConstructorWithDependencyDemo.java b/tests/utils/src/main/java/samples/constructor/PublicConstructorWithDependencyDemo.java
new file mode 100644
index 0000000..9f25625
--- /dev/null
+++ b/tests/utils/src/main/java/samples/constructor/PublicConstructorWithDependencyDemo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.constructor;
+
+import samples.Service;
+
+/**
+ * This class is used to demonstrate that error messages are correct when a
+ * constructor is not found.
+ */
+public class PublicConstructorWithDependencyDemo {
+
+ private final Service service;
+
+ public PublicConstructorWithDependencyDemo(Service service) {
+ this.service = service;
+ }
+
+ public Service getService() {
+ return service;
+ }
+
+ public void aMethod() {
+ System.out.println("Does basically nothing");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/constructorargs/ConstructorArgsDemo.java b/tests/utils/src/main/java/samples/constructorargs/ConstructorArgsDemo.java
new file mode 100644
index 0000000..de82623
--- /dev/null
+++ b/tests/utils/src/main/java/samples/constructorargs/ConstructorArgsDemo.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.constructorargs;
+
+public class ConstructorArgsDemo {
+
+ private static final String DEFAULT = "default";
+
+ private final String secret;
+
+ public ConstructorArgsDemo(String secret) {
+ this.secret = secret;
+ }
+
+ public ConstructorArgsDemo() {
+ secret = DEFAULT;
+ }
+
+ public String getTheSecret() {
+ return theSecretIsPrivate();
+ }
+
+ private String theSecretIsPrivate() {
+ return secret;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/enummocking/AnotherSomeObjectInterfaceImpl.java b/tests/utils/src/main/java/samples/enummocking/AnotherSomeObjectInterfaceImpl.java
new file mode 100644
index 0000000..7ee29d4
--- /dev/null
+++ b/tests/utils/src/main/java/samples/enummocking/AnotherSomeObjectInterfaceImpl.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.enummocking;
+
+/**
+ *
+ */
+public class AnotherSomeObjectInterfaceImpl implements SomeObjectInterface {
+}
diff --git a/tests/utils/src/main/java/samples/enummocking/EnumWithConstructor.java b/tests/utils/src/main/java/samples/enummocking/EnumWithConstructor.java
new file mode 100644
index 0000000..d927a6c
--- /dev/null
+++ b/tests/utils/src/main/java/samples/enummocking/EnumWithConstructor.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.enummocking;
+
+/**
+ *
+ */
+public enum EnumWithConstructor {
+
+ SOME_ENUM_VALUE(
+
+ ) {
+ @Override
+ public SomeObjectInterface create() {
+ return new SomeObjectInterfaceImpl();
+ }
+ };
+
+ public abstract SomeObjectInterface create();
+
+}
diff --git a/tests/utils/src/main/java/samples/enummocking/MyEnum.java b/tests/utils/src/main/java/samples/enummocking/MyEnum.java
new file mode 100644
index 0000000..fddb0a7
--- /dev/null
+++ b/tests/utils/src/main/java/samples/enummocking/MyEnum.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.enummocking;
+
+public enum MyEnum {
+
+ MY_VALUE;
+
+ public static String getString() {
+ return MY_VALUE.toString();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/enummocking/SomeObjectInterface.java b/tests/utils/src/main/java/samples/enummocking/SomeObjectInterface.java
new file mode 100644
index 0000000..3bfd769
--- /dev/null
+++ b/tests/utils/src/main/java/samples/enummocking/SomeObjectInterface.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.enummocking;
+
+/**
+ *
+ */
+public interface SomeObjectInterface {
+}
diff --git a/tests/utils/src/main/java/samples/enummocking/SomeObjectInterfaceImpl.java b/tests/utils/src/main/java/samples/enummocking/SomeObjectInterfaceImpl.java
new file mode 100644
index 0000000..6611190
--- /dev/null
+++ b/tests/utils/src/main/java/samples/enummocking/SomeObjectInterfaceImpl.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.enummocking;
+
+/**
+ *
+ */
+public class SomeObjectInterfaceImpl implements SomeObjectInterface {
+}
diff --git a/tests/utils/src/main/java/samples/equalswithgetclass/EqualsWithGetClass.java b/tests/utils/src/main/java/samples/equalswithgetclass/EqualsWithGetClass.java
new file mode 100644
index 0000000..42df35c
--- /dev/null
+++ b/tests/utils/src/main/java/samples/equalswithgetclass/EqualsWithGetClass.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.equalswithgetclass;
+
+/**
+ * Class that implements an equals method that contains a call to getClass();
+ */
+public class EqualsWithGetClass {
+
+ private final String myString;
+
+ public EqualsWithGetClass(String myString) {
+ super();
+ this.myString = myString;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((myString == null) ? 0 : myString.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ EqualsWithGetClass other = (EqualsWithGetClass) obj;
+ if (myString == null) {
+ if (other.myString != null)
+ return false;
+ } else if (!myString.equals(other.myString))
+ return false;
+ return true;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/ExpectNewDemo.java b/tests/utils/src/main/java/samples/expectnew/ExpectNewDemo.java
new file mode 100644
index 0000000..ae54abf
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/ExpectNewDemo.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+import samples.Service;
+import samples.newmocking.MyClass;
+
+import java.io.*;
+import java.util.Date;
+
+public class ExpectNewDemo {
+
+ private int dummyField;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + dummyField;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final ExpectNewDemo other = (ExpectNewDemo) obj;
+ if (dummyField != other.dummyField)
+ return false;
+ return true;
+ }
+
+ public String getMessage() {
+ MyClass myClass = new MyClass();
+ return myClass.getMessage();
+ }
+
+ public String getMessageWithArgument() {
+ MyClass myClass = new MyClass();
+ return myClass.getMessage("test");
+ }
+
+ public void invokeVoidMethod() {
+ MyClass myClass = new MyClass();
+ myClass.voidMethod();
+ }
+
+ /**
+ * The purpose of the method is to demonstrate that a test case can mock the
+ * new instance call and throw an exception upon instantiation.
+ */
+ public void throwExceptionWhenInvoction() {
+ new MyClass();
+ }
+
+ /**
+ * The purpose of the method is to demonstrate that a test case can mock the
+ * new instance call and throw an exception upon instantiation.
+ */
+ public void throwExceptionAndWrapInRunTimeWhenInvoction() {
+ try {
+ new MyClass();
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ public String multipleNew() {
+ MyClass myClass1 = new MyClass();
+ MyClass myClass2 = new MyClass();
+
+ final String message1 = myClass1.getMessage();
+ final String message2 = myClass2.getMessage();
+ return message1 + message2;
+ }
+
+ public void simpleMultipleNew() {
+ new MyClass();
+ new MyClass();
+ new MyClass();
+ }
+
+ @SuppressWarnings("unused")
+ private void simpleMultipleNewPrivate() {
+ new MyClass();
+ new MyClass();
+ new MyClass();
+ }
+
+ public void simpleSingleNew() {
+ new MyClass();
+ }
+
+ public Date makeDate() {
+ return new Date();
+ }
+
+ public boolean fileExists(String name) {
+ return new File(name).exists();
+ }
+
+ public InputStream alternativePath() {
+ try {
+ return new DataInputStream(null);
+ } catch (RuntimeException e) {
+ return new ByteArrayInputStream(new byte[0]);
+ }
+ }
+
+ public String newWithArguments(Service service, int times) {
+ return new ExpectNewServiceUser(service, times).useService();
+ }
+
+ public String newWithWrongArguments(Service service, int times) {
+ return new ExpectNewServiceUser(service, times * 2).useService();
+ }
+
+ public String[] newVarArgs(String... strings) {
+ return new VarArgsConstructorDemo(strings).getAllMessages();
+ }
+
+ public Service[] newVarArgs(Service... services) {
+ return new VarArgsConstructorDemo(services).getAllServices();
+ }
+ public int[] newVarArgs(float myFloat, int ... ints) {
+ return new VarArgsConstructorDemo(myFloat, ints).getInts();
+ }
+
+ public byte[][] newVarArgs(byte[]... bytes) {
+ return new VarArgsConstructorDemo(bytes).getByteArrays();
+ }
+
+ public byte[][] newVarArgsWithMatchers() {
+ return new VarArgsConstructorDemo(new byte[] { 42 }, new byte[] { 17 }).getByteArrays();
+ }
+
+ public void fileWriter(String name, String msg) throws IOException {
+ new FileWriter(name).write(msg);
+ }
+
+ public void fileWriterPrint(String name, String msg) throws IOException {
+ new PrintWriter(new FileWriter(name)).write(msg);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/ExpectNewOfFinalSystemClassDemo.java b/tests/utils/src/main/java/samples/expectnew/ExpectNewOfFinalSystemClassDemo.java
new file mode 100644
index 0000000..91de8e4
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/ExpectNewOfFinalSystemClassDemo.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+public class ExpectNewOfFinalSystemClassDemo {
+
+ public char getFirstChar() {
+ String myString = new String("My String");
+ return myString.charAt(0);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/ExpectNewServiceUser.java b/tests/utils/src/main/java/samples/expectnew/ExpectNewServiceUser.java
new file mode 100644
index 0000000..f922540
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/ExpectNewServiceUser.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+import samples.Service;
+
+public class ExpectNewServiceUser {
+
+ private final Service service;
+ private final int times;
+
+ ExpectNewServiceUser(Service service, int times) {
+ this.service = service;
+ this.times = times;
+ }
+
+ public String useService() {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < times; i++) {
+ builder.append(service.getServiceMessage());
+ }
+ return builder.toString();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/ExpectNewWithMultipleCtorDemo.java b/tests/utils/src/main/java/samples/expectnew/ExpectNewWithMultipleCtorDemo.java
new file mode 100644
index 0000000..4259de0
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/ExpectNewWithMultipleCtorDemo.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+import samples.Service;
+
+public class ExpectNewWithMultipleCtorDemo {
+
+ private final Service service;
+ private final int times;
+
+ public ExpectNewWithMultipleCtorDemo(Service service) {
+ this(service, 1);
+ }
+
+ public ExpectNewWithMultipleCtorDemo(Service service, int times) {
+ this.service = service;
+ this.times = times;
+ }
+
+ public String useService() {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < times; i++) {
+ builder.append(service.getServiceMessage());
+ }
+ return builder.toString();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/NewFileExample.java b/tests/utils/src/main/java/samples/expectnew/NewFileExample.java
new file mode 100644
index 0000000..5b2c4b5
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/NewFileExample.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+import java.io.File;
+
+/**
+ * Used to demonstrate PowerMock's ability to mock new instance calls.
+ */
+public class NewFileExample {
+
+ public boolean createDirectoryStructure(String directoryPath) {
+ File directory = new File(directoryPath);
+
+ if (directory.exists()) {
+ throw new IllegalArgumentException("\"" + directoryPath + "\" already exists.");
+ }
+
+ return directory.mkdirs();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperDemo.java b/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperDemo.java
new file mode 100644
index 0000000..16a60d3
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperDemo.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+/**
+ * Used to demonstrate PowerMocks ability to deal with overloaded constructors
+ * of primitive/wrapper types.
+ */
+public class PrimitiveAndWrapperDemo {
+
+ private final int myInt;
+
+ public PrimitiveAndWrapperDemo(int myInt) {
+ this.myInt = myInt;
+ }
+
+ public PrimitiveAndWrapperDemo(Integer myInt) {
+ this.myInt = myInt;
+ }
+
+ public int getMyInt() {
+ return myInt;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperUser.java b/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperUser.java
new file mode 100644
index 0000000..8fcc7ce
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/PrimitiveAndWrapperUser.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+/**
+ * Used to demonstrate PowerMocks ability to deal with overloaded constructors
+ * of primitive/wrapper types.
+ */
+public class PrimitiveAndWrapperUser {
+
+ public int useThem() {
+ PrimitiveAndWrapperDemo demo1 = new PrimitiveAndWrapperDemo(Integer.valueOf(42));
+ PrimitiveAndWrapperDemo demo2 = new PrimitiveAndWrapperDemo(21);
+ return demo1.getMyInt() + demo2.getMyInt();
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/src/main/java/samples/expectnew/VarArgsConstructorDemo.java b/tests/utils/src/main/java/samples/expectnew/VarArgsConstructorDemo.java
new file mode 100644
index 0000000..b4a283b
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectnew/VarArgsConstructorDemo.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectnew;
+
+import samples.Service;
+
+public class VarArgsConstructorDemo {
+
+ private final String[] strings;
+ private final Service[] services;
+ private final byte[][] byteArrays;
+ private final int[] ints;
+
+ public VarArgsConstructorDemo(String... strings) {
+ this.strings = strings;
+ this.services = new Service[0];
+ this.byteArrays = new byte[0][0];
+ this.ints = new int[0];
+ }
+
+ public VarArgsConstructorDemo(byte[]... byteArrays) {
+ this.byteArrays = byteArrays;
+ this.services = new Service[0];
+ this.strings = new String[0];
+ this.ints = new int[0];
+ }
+
+ public VarArgsConstructorDemo(Service... services) {
+ this.services = services;
+ this.strings = new String[0];
+ this.byteArrays = new byte[0][0];
+ this.ints = new int[0];
+ }
+
+ public VarArgsConstructorDemo(float myFloat, int... ints) {
+ this.ints = ints;
+ this.services = new Service[0];
+ strings = new String[0];
+ byteArrays = new byte[0][0];
+ }
+
+ public String[] getAllMessages() {
+ return strings;
+ }
+
+ public Service[] getAllServices() {
+ return services;
+ }
+
+ public byte[][] getByteArrays() {
+ return byteArrays;
+ }
+
+ public int[] getInts() {
+ return ints;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/expectvoid/ExpectVoidDemo.java b/tests/utils/src/main/java/samples/expectvoid/ExpectVoidDemo.java
new file mode 100644
index 0000000..ad400de
--- /dev/null
+++ b/tests/utils/src/main/java/samples/expectvoid/ExpectVoidDemo.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.expectvoid;
+
+public class ExpectVoidDemo {
+
+ public void invokeAPrivateVoidMethod(int something) {
+ privateInvoke(something);
+ }
+
+ private void privateInvoke(int something) {
+ System.out.println("Error in test privateInvoke in class "
+ + ExpectVoidDemo.class.getSimpleName());
+ }
+}
diff --git a/tests/utils/src/main/java/samples/fieldmock/FieldInitializerDemo.java b/tests/utils/src/main/java/samples/fieldmock/FieldInitializerDemo.java
new file mode 100644
index 0000000..70e2959
--- /dev/null
+++ b/tests/utils/src/main/java/samples/fieldmock/FieldInitializerDemo.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.fieldmock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class FieldInitializerDemo {
+
+ private Map<Integer, String> map = new HashMap<Integer, String>();
+
+ private static Map<Integer, String> staticMap = new HashMap<Integer, String>();
+
+ private static Map<Integer, String> staticMap2;
+ static {
+ staticMap2 = new HashMap<Integer, String>();
+ System.out.println("### Static println!");
+ }
+
+ public String getFromMap(int index) {
+ System.out.println("getFromMap class = " + map.getClass());
+ System.out.println("staticMap = " + staticMap);
+ System.out.println("staticMap2 = " + staticMap2);
+ return map.get(index);
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/finalmocking/FinalDemo.java b/tests/utils/src/main/java/samples/finalmocking/FinalDemo.java
new file mode 100644
index 0000000..54f9e83
--- /dev/null
+++ b/tests/utils/src/main/java/samples/finalmocking/FinalDemo.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.finalmocking;
+
+import samples.simplemix.SimpleMix;
+import samples.simplereturn.SimpleReturnExample;
+
+public final class FinalDemo {
+
+ public final String say(String string) {
+ return "Hello " + string;
+ }
+
+ public final void finalVoidCaller() {
+ finalVoidCallee();
+ }
+
+ public final void finalVoidCallee() {
+ System.err.println("void method");
+ }
+
+ public final native String sayFinalNative(String string);
+
+ public final SimpleReturnExample simpleReturnExample() {
+ return new SimpleReturnExample();
+ }
+
+ public final SimpleMix simpleMix() {
+ return new SimpleMix();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/finalmocking/HoldingFinalDemo.java b/tests/utils/src/main/java/samples/finalmocking/HoldingFinalDemo.java
new file mode 100644
index 0000000..86a1315
--- /dev/null
+++ b/tests/utils/src/main/java/samples/finalmocking/HoldingFinalDemo.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.finalmocking;
+
+public final class HoldingFinalDemo {
+
+ public FinalDemo getFinalDemo() {
+ return null;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/finalmocking/StaticHoldingFinalDemo.java b/tests/utils/src/main/java/samples/finalmocking/StaticHoldingFinalDemo.java
new file mode 100644
index 0000000..45712b2
--- /dev/null
+++ b/tests/utils/src/main/java/samples/finalmocking/StaticHoldingFinalDemo.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.finalmocking;
+
+public class StaticHoldingFinalDemo {
+
+ public static FinalDemo getFinalDemo() {
+ return null;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/hashcode/HashCodeInitializedInCtor.java b/tests/utils/src/main/java/samples/hashcode/HashCodeInitializedInCtor.java
new file mode 100644
index 0000000..4670c4e
--- /dev/null
+++ b/tests/utils/src/main/java/samples/hashcode/HashCodeInitializedInCtor.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.hashcode;
+
+import java.util.HashMap;
+
+public class HashCodeInitializedInCtor {
+ private final HashMap<String, String> hash;
+
+ public HashCodeInitializedInCtor() {
+ hash = new HashMap<String, String>();
+ }
+
+ public static HashCodeInitializedInCtor newFaults() {
+ HashCodeInitializedInCtor fault = new HashCodeInitializedInCtor();
+ return fault;
+ }
+
+ @Override
+ public final int hashCode() {
+ return hash.hashCode();
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/injectmocks/DependencyHolder.java b/tests/utils/src/main/java/samples/injectmocks/DependencyHolder.java
new file mode 100644
index 0000000..824220d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/injectmocks/DependencyHolder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.injectmocks;
+
+import samples.finalmocking.FinalDemo;
+
+/**
+ * Simple class used to demonstrate setter injection..
+ */
+public class DependencyHolder {
+
+ private FinalDemo finalDemo;
+
+ public FinalDemo getFinalDemo() {
+ return finalDemo;
+ }
+
+ public void setFinalDemo(FinalDemo finalDemo) {
+ this.finalDemo = finalDemo;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/injectmocks/DependencyHolderQualifier.java b/tests/utils/src/main/java/samples/injectmocks/DependencyHolderQualifier.java
new file mode 100644
index 0000000..7669c85
--- /dev/null
+++ b/tests/utils/src/main/java/samples/injectmocks/DependencyHolderQualifier.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package samples.injectmocks;
+
+import samples.finalmocking.FinalDemo;
+
+/**
+ * Simple class used to demonstrate setter injection..
+ */
+ at SuppressWarnings({"WeakerAccess", "unused"})
+public class DependencyHolderQualifier {
+
+ private FinalDemo finalDemo;
+ private FinalDemo finalDemoQualifier;
+
+ public FinalDemo getFinalDemo() {
+ return finalDemo;
+ }
+
+ public void setFinalDemo(FinalDemo finalDemo) {
+ this.finalDemo = finalDemo;
+ }
+
+ public FinalDemo getFinalDemoQualifier() {
+ return finalDemoQualifier;
+ }
+
+ public void setFinalDemoQualifier(FinalDemo finalDemoQualifier) {
+ this.finalDemoQualifier = finalDemoQualifier;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/injectmocks/InjectDemo.java b/tests/utils/src/main/java/samples/injectmocks/InjectDemo.java
new file mode 100644
index 0000000..cdaa465
--- /dev/null
+++ b/tests/utils/src/main/java/samples/injectmocks/InjectDemo.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.injectmocks;
+
+/**
+ *
+ */
+ at SuppressWarnings({"SameReturnValue", "unused"})
+public class InjectDemo {
+
+ @SuppressWarnings("unused")
+ public String getMessage() {
+ return say("hello");
+ }
+
+ @SuppressWarnings("UnusedParameters")
+ private String say(String hello) {
+ return hello;
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolder.java b/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolder.java
new file mode 100644
index 0000000..ea248a6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolder.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package samples.injectmocks;
+
+/**
+ * Simple class used to demonstrate setter injection..
+ */
+ at SuppressWarnings("unused")
+public class InjectDependencyHolder {
+
+ private InjectDemo injectDemo;
+
+ public InjectDemo getInjectDemo() {
+ return injectDemo;
+ }
+
+ public void setInjectDemo(InjectDemo injectDemo) {
+ this.injectDemo = injectDemo;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolderQualifier.java b/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolderQualifier.java
new file mode 100644
index 0000000..f05c24f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/injectmocks/InjectDependencyHolderQualifier.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package samples.injectmocks;
+
+/**
+ * Simple class used to demonstrate setter injection..
+ */
+ at SuppressWarnings("unused")
+public class InjectDependencyHolderQualifier {
+
+ private InjectDemo injectDemo;
+ private InjectDemo injectDemoQualifier;
+
+ public InjectDemo getInjectDemo() {
+ return injectDemo;
+ }
+
+ public void setInjectDemo(InjectDemo injectDemo) {
+ this.injectDemo = injectDemo;
+ }
+
+ public InjectDemo getInjectDemoQualifier() {
+ return injectDemoQualifier;
+ }
+
+ public void setInjectDemoQualifier(InjectDemo injectDemoQualifier) {
+ this.injectDemoQualifier = injectDemoQualifier;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/innerclassmocking/ClassWithNonPrivateInnerClass.java b/tests/utils/src/main/java/samples/innerclassmocking/ClassWithNonPrivateInnerClass.java
new file mode 100644
index 0000000..1f5e88d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/innerclassmocking/ClassWithNonPrivateInnerClass.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.innerclassmocking;
+
+/**
+ * Demonstrates the ability to mock an inner class (if the inner class is not
+ * private).
+ *
+ * @author Johan Haleby
+ */
+public class ClassWithNonPrivateInnerClass {
+
+ public String getMessage() {
+ return new InnerClass().getInnerMessage();
+ }
+
+ public class InnerClass {
+ public String getInnerMessage() {
+ return "A message from an inner class!";
+ }
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/innerclassmocking/ClassWithPrivateInnerClass.java b/tests/utils/src/main/java/samples/innerclassmocking/ClassWithPrivateInnerClass.java
new file mode 100644
index 0000000..069557d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/innerclassmocking/ClassWithPrivateInnerClass.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.innerclassmocking;
+
+/**
+ * Used for demonstration of the ability to mock methods from a private inner
+ * class. Due to limitations in Javassist (which doesn't seem to load inner
+ * classes correctly??) we cannot mock private methods in inner classes. It
+ * doesn't seem to have any effect when modifing the method modifier and setting
+ * the method to public when loading the class by the mock class loader (but
+ * why? Could be because the outer class has already been loaded?!).
+ *
+ */
+public class ClassWithPrivateInnerClass {
+ public String getMessage() {
+ return new InnerClass().getInnerMessage();
+ }
+
+ private class InnerClass {
+ public String getInnerMessage() {
+ return "A message from an inner class!";
+ }
+ }
+}
diff --git a/tests/utils/src/main/java/samples/interfacefieldchange/InterfaceWithStaticFinalField.java b/tests/utils/src/main/java/samples/interfacefieldchange/InterfaceWithStaticFinalField.java
new file mode 100644
index 0000000..e38bafa
--- /dev/null
+++ b/tests/utils/src/main/java/samples/interfacefieldchange/InterfaceWithStaticFinalField.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.interfacefieldchange;
+
+/**
+ * The purpose of the simple class is to demonstrate PowerMocks (possibly
+ * future) ability to change static final fields in an interface. This is
+ * normally not possible (the simple byte-code manipulation approach of removing
+ * the final modifier doesn't work for interfaces since all static fields
+ * <i>must</i> be final in interfaces according to the specification).
+ */
+public interface InterfaceWithStaticFinalField {
+ static final String MY_STRING = "My value";
+}
diff --git a/tests/utils/src/main/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsage.java b/tests/utils/src/main/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsage.java
new file mode 100644
index 0000000..071cf24
--- /dev/null
+++ b/tests/utils/src/main/java/samples/interfacemethodfinding/InterfaceMethodHierarchyUsage.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.interfacemethodfinding;
+
+import org.powermock.reflect.internal.WhiteboxImpl;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+
+/**
+ * There was a bug in PowerMock 1.2 and its predecessors that made PowerMock
+ * {@link WhiteboxImpl#getMethod(Class, Class...)} fail when invoking proxified
+ * interface methods declared in extended interfaces. E.g. if interface A
+ * extends B & C and a method was declared in B it wouldn't be found by
+ * {@link WhiteboxImpl#getMethod(Class, Class...)} since it only used to
+ * traverse the class hierarchy and not the structure of the extended
+ * interfaces. This was fixed in version 1.3 and this class is used to
+ * demonstrate the issue.
+ * <p>
+ * Thanks to Lokesh Vaddi for finding this bug and to provide an example.
+ */
+public class InterfaceMethodHierarchyUsage {
+
+ public void usePreparedStatement() throws Exception {
+ Connection conn = null;
+ // PreparedStatement extends other interfaces, this is the point of
+ // interest.
+ PreparedStatement prepared = null;
+ try {
+ conn = WsUtil.getConnection();
+ prepared = conn.prepareStatement("select * from emp");
+ } catch (Exception e) {
+ System.out.println(e);
+
+ } finally {
+ conn.close();
+ prepared.close();
+ }
+ }
+}
diff --git a/tests/utils/src/main/java/samples/interfacemethodfinding/WsUtil.java b/tests/utils/src/main/java/samples/interfacemethodfinding/WsUtil.java
new file mode 100644
index 0000000..c4c7fea
--- /dev/null
+++ b/tests/utils/src/main/java/samples/interfacemethodfinding/WsUtil.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.interfacemethodfinding;
+
+import java.sql.Connection;
+
+/**
+ * Dummy class that is used to setup expectations for the
+ * {@link InterfaceMethodHierarchyUsage}.
+ */
+public class WsUtil {
+
+ public static Connection getConnection() throws Exception {
+
+ Connection conn = null;
+
+ return conn;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/java/ClassInsideJavaPackage.java b/tests/utils/src/main/java/samples/java/ClassInsideJavaPackage.java
new file mode 100644
index 0000000..0ed7d85
--- /dev/null
+++ b/tests/utils/src/main/java/samples/java/ClassInsideJavaPackage.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.java;
+
+public final class ClassInsideJavaPackage {
+
+ public final String mockMe() {
+ return "string";
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/largemethod/MethodExceedingJvmLimit.java b/tests/utils/src/main/java/samples/largemethod/MethodExceedingJvmLimit.java
new file mode 100644
index 0000000..8f9a852
--- /dev/null
+++ b/tests/utils/src/main/java/samples/largemethod/MethodExceedingJvmLimit.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.largemethod;
+
+/**
+ * Example of class with method which after instrumentation is larger than JVM limit.
+ */
+public class MethodExceedingJvmLimit {
+
+ /**
+ * Method size after instrumentation is equal to 91265.
+ */
+ public static String init() {
+ String a = "A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";a+="A";
+ return a;
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemo.java b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemo.java
new file mode 100644
index 0000000..2787f6b
--- /dev/null
+++ b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemo.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.methodhierarchy;
+
+public class MethodInvocationDemo extends MethodInvocationDemoParent {
+
+ @SuppressWarnings("unused")
+ private String getString() {
+ return getTheString();
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoGrandParent.java b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoGrandParent.java
new file mode 100644
index 0000000..7c84162
--- /dev/null
+++ b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoGrandParent.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.methodhierarchy;
+
+public class MethodInvocationDemoGrandParent {
+
+ protected String getTheString() {
+ return "a string from MethodInvocationDemoGrandParent";
+ }
+
+ @SuppressWarnings("unused")
+ private String getString() {
+ return "MethodInvocationDemoGrandParent";
+ }
+
+ @SuppressWarnings("unused")
+ private String getString(int index) {
+ return "MethodInvocationDemoGrandParent: " + index;
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoParent.java b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoParent.java
new file mode 100644
index 0000000..18b91dd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/methodhierarchy/MethodInvocationDemoParent.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.methodhierarchy;
+
+public class MethodInvocationDemoParent extends MethodInvocationDemoGrandParent {
+
+ @Override
+ protected String getTheString() {
+ return "MethodInvocationDemoParent wrapped " + super.getTheString();
+ }
+
+ @SuppressWarnings("unused")
+ private String getString() {
+ return "MethodInvocationDemoParent";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/ResultCalculator.java b/tests/utils/src/main/java/samples/mockpolicy/ResultCalculator.java
new file mode 100644
index 0000000..f27092a
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/ResultCalculator.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy;
+
+public class ResultCalculator {
+ private int operand;
+
+ public ResultCalculator(int operand) {
+ this.operand = operand;
+ }
+
+ public double calculate() {
+ return Math.PI*operand;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/SimpleClassWithADependency.java b/tests/utils/src/main/java/samples/mockpolicy/SimpleClassWithADependency.java
new file mode 100644
index 0000000..bb3e64b
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/SimpleClassWithADependency.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy;
+
+
+public class SimpleClassWithADependency {
+
+ private ResultCalculator calculator;
+
+ public double getResult() {
+ return calculator.calculate();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethod.java b/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethod.java
new file mode 100644
index 0000000..894e992
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethod.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy;
+
+public class SomeClassWithAMethod extends SomeClassWithAMethodParent {
+
+ @Override
+ public double getResult() {
+ return super.getResult() * 2;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethodParent.java b/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethodParent.java
new file mode 100644
index 0000000..6a96d08
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/SomeClassWithAMethodParent.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy;
+
+public class SomeClassWithAMethodParent {
+
+ public double getResult() {
+ return new ResultCalculator(4).calculate();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/NativeResult.java b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/NativeResult.java
new file mode 100644
index 0000000..444fe62
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/NativeResult.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy.frameworkexample;
+
+public class NativeResult {
+
+ private final String result;
+
+ public NativeResult(String result) {
+ this.result = result;
+ }
+
+ public String get() {
+ return result;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFramework.java b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFramework.java
new file mode 100644
index 0000000..aa9a8c7
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFramework.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy.frameworkexample;
+
+public class SimpleFramework {
+
+ static {
+ System.loadLibrary("framework.dll");
+ }
+
+ public NativeResult doNativeStuff(String nativeStuffToDo) {
+ return new NativeResult(nativeStuffToDo);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFrameworkUser.java b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFrameworkUser.java
new file mode 100644
index 0000000..27675b1
--- /dev/null
+++ b/tests/utils/src/main/java/samples/mockpolicy/frameworkexample/SimpleFrameworkUser.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.mockpolicy.frameworkexample;
+
+public class SimpleFrameworkUser {
+
+ public String performComplexOperation(String operation) {
+ return new SimpleFramework().doNativeStuff(operation).get();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/nativemocking/NativeMockingSample.java b/tests/utils/src/main/java/samples/nativemocking/NativeMockingSample.java
new file mode 100644
index 0000000..8d535d6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/nativemocking/NativeMockingSample.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.nativemocking;
+
+/**
+ * The purpose of this class is to invoke a native method in a collaborator.
+ */
+public class NativeMockingSample {
+
+ private final NativeService nativeService;
+
+ public NativeMockingSample(NativeService nativeService) {
+ this.nativeService = nativeService;
+ }
+
+ public String invokeNativeMethod(String param) {
+ return nativeService.invokeNative(param);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/nativemocking/NativeService.java b/tests/utils/src/main/java/samples/nativemocking/NativeService.java
new file mode 100644
index 0000000..4a8aa4d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/nativemocking/NativeService.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.nativemocking;
+
+/**
+ * The purpose of this class is to demonstrate that it's possible to mock native
+ * methods using plain EasyMock class extensions.
+ */
+public class NativeService {
+
+ public native String invokeNative(String nativeParameter);
+
+}
diff --git a/tests/utils/src/main/java/samples/newmocking/MyClass.java b/tests/utils/src/main/java/samples/newmocking/MyClass.java
new file mode 100644
index 0000000..679f9df
--- /dev/null
+++ b/tests/utils/src/main/java/samples/newmocking/MyClass.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.newmocking;
+
+public class MyClass {
+
+ public String getMessage() {
+ return "Hello world";
+ }
+
+ public String getMessage(String message) {
+ return "Hello world: " + message;
+ }
+
+ public void voidMethod() {
+ System.out.println("Void method!");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/newmocking/NewDemo.java b/tests/utils/src/main/java/samples/newmocking/NewDemo.java
new file mode 100644
index 0000000..37e2096
--- /dev/null
+++ b/tests/utils/src/main/java/samples/newmocking/NewDemo.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.newmocking;
+
+public final class NewDemo {
+
+ public void methodUnderTest()
+ {
+ SomeDependency loadingPool = new SomeDependency();
+ loadingPool.complete();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/newmocking/SomeDependency.java b/tests/utils/src/main/java/samples/newmocking/SomeDependency.java
new file mode 100644
index 0000000..9da3796
--- /dev/null
+++ b/tests/utils/src/main/java/samples/newmocking/SomeDependency.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.newmocking;
+
+
+public class SomeDependency {
+
+ private String thing="complete";
+
+ void complete() {
+ System.out.println(thing.toString()); // PowerMockBugPartATest gives NPE here, PowerMockBugPartBTest works
+ }
+}
+
diff --git a/tests/utils/src/main/java/samples/newmocking/StupidNew.java b/tests/utils/src/main/java/samples/newmocking/StupidNew.java
new file mode 100644
index 0000000..d2f1be7
--- /dev/null
+++ b/tests/utils/src/main/java/samples/newmocking/StupidNew.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.newmocking;
+
+public class StupidNew {
+
+ public String getMessage() {
+ MyClass myClass = new MyClass();
+ return myClass.getMessage();
+ }
+
+ public String getMessageWithArgument() {
+ MyClass myClass = new MyClass();
+ return myClass.getMessage("test");
+ }
+
+ public void invokeVoidMethod() {
+ MyClass myClass = new MyClass();
+ myClass.voidMethod();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/nice/NiceDemo.java b/tests/utils/src/main/java/samples/nice/NiceDemo.java
new file mode 100644
index 0000000..1ade927
--- /dev/null
+++ b/tests/utils/src/main/java/samples/nice/NiceDemo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.nice;
+
+public class NiceDemo {
+
+ public void callAThenB() {
+ A("String");
+ B("String 2");
+ }
+
+ void A(String aString) {
+ // Does nothing
+ }
+
+ void B(String aString) {
+ // Does nothing
+ }
+}
diff --git a/tests/utils/src/main/java/samples/overloading/OverloadedMethodsExample.java b/tests/utils/src/main/java/samples/overloading/OverloadedMethodsExample.java
new file mode 100644
index 0000000..7f45a9e
--- /dev/null
+++ b/tests/utils/src/main/java/samples/overloading/OverloadedMethodsExample.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.overloading;
+
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+
+public class OverloadedMethodsExample {
+ public static void overloadedMethodWithOneArgument(Parent parent) {
+ }
+
+ public static void overloadedMethodWithOneArgument(ChildA child) {
+ }
+
+ public static void overloadedMethodWithTwoArguments(Parent parent, ChildA child) {
+ }
+
+ public static void overloadedMethodWithTwoArguments(Parent parent1, Parent parent2) {
+ }
+}
diff --git a/tests/utils/src/main/java/samples/overloading/OverloadingDemo.java b/tests/utils/src/main/java/samples/overloading/OverloadingDemo.java
new file mode 100644
index 0000000..ed10949
--- /dev/null
+++ b/tests/utils/src/main/java/samples/overloading/OverloadingDemo.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.overloading;
+
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+
+/**
+ * Demonstrates that PowerMock correctly invoke overloaded methods from the
+ * MockGateway.
+ */
+public class OverloadingDemo {
+
+ public void performSingleOverloadedArgumentTest() {
+ Parent object = new ChildA();
+ OverloadedMethodsExample.overloadedMethodWithOneArgument(object);
+ }
+
+ public void performMethodOverloadTestWhenBothArgumentSame() {
+ Parent object1 = new ChildA();
+ Parent object2 = new ChildA();
+ OverloadedMethodsExample.overloadedMethodWithTwoArguments(object1, object2);
+ }
+
+ public void performMethodOverloadTestWithOneArgumentSameAndOneDiffernt() {
+ Parent object1 = new ChildA();
+ Parent object2 = new Parent();
+ OverloadedMethodsExample.overloadedMethodWithTwoArguments(object2, object1);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameName.java b/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameName.java
new file mode 100644
index 0000000..3bb69dd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameName.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.overloading;
+
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+
+public class StaticAndInstanceMethodWithSameName {
+ public void overloaded(Parent parent) {
+ }
+
+ public static void overloaded(ChildA child) {
+ }
+}
diff --git a/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameNameUser.java b/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameNameUser.java
new file mode 100644
index 0000000..ed6a362
--- /dev/null
+++ b/tests/utils/src/main/java/samples/overloading/StaticAndInstanceMethodWithSameNameUser.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.overloading;
+
+import samples.classhierarchy.ChildA;
+import samples.classhierarchy.Parent;
+
+/**
+ * Demonstrates that PowerMock correctly methods that seam to be overloaded but
+ * differ because one is static and one is instance.
+ */
+public class StaticAndInstanceMethodWithSameNameUser {
+
+ public void performInstaceInvocation(StaticAndInstanceMethodWithSameName object) {
+ Parent child = new ChildA();
+ object.overloaded(child);
+ }
+
+ public void performStaticInvocation() {
+ Parent child = new ChildA();
+ StaticAndInstanceMethodWithSameName.overloaded((ChildA) child);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/packageprivate/PackagePrivateClass.java b/tests/utils/src/main/java/samples/packageprivate/PackagePrivateClass.java
new file mode 100644
index 0000000..5692523
--- /dev/null
+++ b/tests/utils/src/main/java/samples/packageprivate/PackagePrivateClass.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.packageprivate;
+
+/**
+ * This class demonstrates the ability for PowerMock to mock package private
+ * classes. This is normally not an issue but since we've changed the CgLib
+ * naming policy to allow for signed mocking PowerMock needs to byte-code
+ * manipulate this class.
+ */
+class PackagePrivateClass {
+
+ public int getValue() {
+ return returnAValue();
+ }
+
+ private int returnAValue() {
+ return 82;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/MockSelfDemo.java b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemo.java
new file mode 100644
index 0000000..44e54db
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemo.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+import java.sql.Connection;
+
+public class MockSelfDemo {
+
+ private int hello;
+
+ @SuppressWarnings("unused")
+ private MockSelfDemo() {
+ hello = 42;
+ }
+
+ public MockSelfDemo(int hello) {
+ this.hello = hello;
+ }
+
+ public MockSelfDemo(Object string) {
+ this.hello = 4;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + hello;
+ return result;
+ }
+
+ protected String establishConnection(Connection conn) throws Exception {
+ if (conn== null) {
+ return "works";
+ } else {
+ return "doesn't work";
+ }
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final MockSelfDemo other = (MockSelfDemo) obj;
+ if (hello != other.hello)
+ return false;
+ return true;
+ }
+
+ public String aMethod() {
+ aMethod2();
+ return getString("world");
+ }
+
+ public void aMethod2() {
+
+ }
+
+ public String getTwoStrings() {
+ return getString() + getString("world2");
+ }
+
+ private String getString() {
+ return "A String";
+ }
+
+ public String getString(String string) {
+ return "Hello " + string;
+ }
+
+ public String getString2(String string) {
+ return "Hello " + string;
+ }
+
+ public String getString2() {
+ return "Hello world";
+ }
+
+ public int timesTwo(Integer anInt) {
+ return anInt * 2;
+ }
+
+ public int timesTwo(int anInt) {
+ return anInt * 2;
+ }
+
+ public int timesThree(int anInt) {
+ return anInt * 3;
+ }
+
+ public int getConstructorValue() {
+ return hello;
+ }
+
+ public static int getSomething() {
+ int retVal = methodToBeStubbed();
+ retVal = retVal * 2;
+ return retVal;
+ }
+
+ public static int methodToBeStubbed() {
+ return 6;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoSubClass.java b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoSubClass.java
new file mode 100644
index 0000000..46cc2f4
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoSubClass.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+public class MockSelfDemoSubClass {
+
+ public String getAMessage() {
+ return "A message";
+ }
+
+ protected String getAProtectedMessage() {
+ return "protected";
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoWithSubClass.java b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoWithSubClass.java
new file mode 100644
index 0000000..9fd96dd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/MockSelfDemoWithSubClass.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+public class MockSelfDemoWithSubClass extends MockSelfDemoSubClass {
+
+ public String getMessage() {
+ return getInternalMessage() + getAMessage();
+ }
+
+ public String getSecondMessage() {
+ return getAProtectedMessage();
+ }
+
+ private String getInternalMessage() {
+ return "Internal message";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/MockSelfWithNoDefaultConstructorDemo.java b/tests/utils/src/main/java/samples/partialmocking/MockSelfWithNoDefaultConstructorDemo.java
new file mode 100644
index 0000000..62611f6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/MockSelfWithNoDefaultConstructorDemo.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+public class MockSelfWithNoDefaultConstructorDemo {
+
+ private int hello;
+
+ public MockSelfWithNoDefaultConstructorDemo(int hello) {
+ this.hello = hello;
+ }
+
+ public String aMethod() {
+ aMethod2();
+ return "hello = " + hello;
+ }
+
+ public void aMethod2() {
+
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/MockWithStaticStateDemo.java b/tests/utils/src/main/java/samples/partialmocking/MockWithStaticStateDemo.java
new file mode 100644
index 0000000..87edd68
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/MockWithStaticStateDemo.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+public class MockWithStaticStateDemo {
+
+ private static final int state = 5;
+
+ public static int getState() {
+ return state;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/PartialMockingExample.java b/tests/utils/src/main/java/samples/partialmocking/PartialMockingExample.java
new file mode 100644
index 0000000..6179dac
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/PartialMockingExample.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+/**
+ * Simple partial mocking example that should need no byte-code manipulation.
+ */
+public class PartialMockingExample {
+
+ public String methodToTest() {
+ return methodToMock();
+ }
+
+ public String methodToMock() {
+ System.out.println("If you see this the test is failing!");
+ return "REAL VALUE";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/PartialMockingWithConstructor.java b/tests/utils/src/main/java/samples/partialmocking/PartialMockingWithConstructor.java
new file mode 100644
index 0000000..6cd0ae4
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/PartialMockingWithConstructor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+public class PartialMockingWithConstructor {
+ public PartialMockingWithConstructor() {
+ initialize();
+ }
+
+ public void initialize() {
+ }
+
+ public void touch() {
+ }
+}
diff --git a/tests/utils/src/main/java/samples/partialmocking/PrivatePartialMockingExample.java b/tests/utils/src/main/java/samples/partialmocking/PrivatePartialMockingExample.java
new file mode 100644
index 0000000..26a4d7a
--- /dev/null
+++ b/tests/utils/src/main/java/samples/partialmocking/PrivatePartialMockingExample.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.partialmocking;
+
+/**
+ * Simple partial mocking example that should need no byte-code manipulation.
+ */
+public final class PrivatePartialMockingExample {
+
+ public String methodToTest() {
+ return methodToMock("input");
+ }
+
+ private String methodToMock(String input) {
+ return "REAL VALUE = " + input;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/powermockignore/PowerMockIgnoreDemo.java b/tests/utils/src/main/java/samples/powermockignore/PowerMockIgnoreDemo.java
new file mode 100644
index 0000000..82cc54e
--- /dev/null
+++ b/tests/utils/src/main/java/samples/powermockignore/PowerMockIgnoreDemo.java
@@ -0,0 +1,10 @@
+package samples.powermockignore;
+
+import javax.swing.*;
+
+public class PowerMockIgnoreDemo {
+
+ public void showDialog() {
+ JOptionPane.showInputDialog("Input:");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/powermockito/MockitoVersion.java b/tests/utils/src/main/java/samples/powermockito/MockitoVersion.java
new file mode 100644
index 0000000..e137b49
--- /dev/null
+++ b/tests/utils/src/main/java/samples/powermockito/MockitoVersion.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package samples.powermockito;
+
+public class MockitoVersion {
+
+ private static final SystemPropertiesMockitoVersion MOCKITO_VERSION = new SystemPropertiesMockitoVersion();
+
+
+ public static boolean isMockito1(){
+ return MOCKITO_VERSION.isMockito1();
+ }
+
+ public static boolean isMockito2(){
+ return MOCKITO_VERSION.isMockito2();
+ }
+
+
+ private static class SystemPropertiesMockitoVersion {
+ private final String version;
+
+ private SystemPropertiesMockitoVersion(){
+ version = System.getProperty("mockitoVersion");
+ }
+
+ private boolean isMockito1(){
+ return version.startsWith("1");
+ }
+
+ public boolean isMockito2() {
+ return version.startsWith("2");
+ }
+ }
+}
diff --git a/tests/utils/src/main/java/samples/privateandfinal/PrivateFinal.java b/tests/utils/src/main/java/samples/privateandfinal/PrivateFinal.java
new file mode 100644
index 0000000..71ebe9d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/privateandfinal/PrivateFinal.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.privateandfinal;
+
+/**
+ * A class used to test the functionality to mock private methods that are also
+ * final.
+ *
+ * @author Johan Haleby
+ */
+public class PrivateFinal {
+ public String say(String name) {
+ return sayIt(name);
+ }
+
+ private final String sayIt(String name) {
+ return "Hello " + name;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/privateandfinal/PrivateFinalOverload.java b/tests/utils/src/main/java/samples/privateandfinal/PrivateFinalOverload.java
new file mode 100644
index 0000000..166c158
--- /dev/null
+++ b/tests/utils/src/main/java/samples/privateandfinal/PrivateFinalOverload.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2014 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.privateandfinal;
+
+/**
+ * A class used to test the functionality of capturing arguments when methods are overloaded and private and final.
+ *
+ * @author Johan Haleby
+ */
+public class PrivateFinalOverload {
+ public String say(String name) {
+ return say("Hello", name);
+ }
+
+ private final String say(String prefix, String name) {
+ return prefix + " " + name;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/privatefield/MockSelfPrivateFieldServiceClass.java b/tests/utils/src/main/java/samples/privatefield/MockSelfPrivateFieldServiceClass.java
new file mode 100644
index 0000000..f05bb4f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/privatefield/MockSelfPrivateFieldServiceClass.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.privatefield;
+
+import samples.Service;
+
+/**
+ * A class that uses a private Service field and no setter. This is approach is
+ * common in DI frameworks like Guice and Wicket IoC.
+ *
+ * @author Johan Haleby
+ */
+public class MockSelfPrivateFieldServiceClass {
+ private Service service;
+
+ public String getCompositeMessage() {
+ final String message = getOwnMessage() + service.getServiceMessage();
+ return message;
+ }
+
+ private String getOwnMessage() {
+ return "My message";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/privatefield/SimplePrivateFieldServiceClass.java b/tests/utils/src/main/java/samples/privatefield/SimplePrivateFieldServiceClass.java
new file mode 100644
index 0000000..582e3b6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/privatefield/SimplePrivateFieldServiceClass.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.privatefield;
+
+import samples.Service;
+
+/**
+ * A class that uses a private Service field and no setter. This is approach is
+ * common in DI frameworks like Guice and Wicket IoC.
+ *
+ * @author Johan Haleby
+ */
+public class SimplePrivateFieldServiceClass {
+ private Service service;
+
+ public String useService() {
+ return service.getServiceMessage();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/privatemocking/PrivateMethodDemo.java b/tests/utils/src/main/java/samples/privatemocking/PrivateMethodDemo.java
new file mode 100644
index 0000000..da1bb53
--- /dev/null
+++ b/tests/utils/src/main/java/samples/privatemocking/PrivateMethodDemo.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.privatemocking;
+
+import javax.activation.FileDataSource;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.Reader;
+
+/**
+ * A class used to test the functionality to mock private methods.
+ *
+ * @author Johan Haleby
+ */
+public class PrivateMethodDemo {
+ public String say(String name) {
+ return sayIt(name);
+ }
+
+ public String enhancedSay(String firstName, String lastName) {
+ return sayIt(firstName, " ", lastName);
+ }
+
+ public String sayYear(String name, int years) {
+ return doSayYear(years, name);
+ }
+
+ private String doSayYear(int years, String name) {
+ return "Hello " + name + ", you are " + years + " old.";
+ }
+
+ private String sayIt(String firstName, String spacing, String lastName) {
+ return "Hello" + firstName + spacing + lastName;
+ }
+
+ private String sayIt(String name) {
+ return "Hello " + name;
+ }
+
+ @SuppressWarnings("unused")
+ private String sayIt() {
+ return "Hello world";
+ }
+
+ public int methodCallingPrimitiveTestMethod() {
+ return aTestMethod(10);
+ }
+
+ public int methodCallingWrappedTestMethod() {
+ return aTestMethod(new Integer(15));
+ }
+
+ private int aTestMethod(int aValue) {
+ return aValue;
+ }
+
+ private Integer aTestMethod(Integer aValue) {
+ return aValue;
+ }
+
+ public void doArrayStuff(String v) {
+ doArrayInternal(new String[]{v});
+ }
+
+ private void doArrayInternal(String[] strings) {
+ }
+
+ public void doObjectStuff(Object o) {
+ doObjectInternal(o);
+ }
+
+ private void doObjectInternal(Object o) {
+ }
+
+ public int invokeVarArgsMethod(int a, int b) {
+ return varArgsMethod(a, b);
+ }
+
+ private int varArgsMethod(int... ints) {
+ int sum = 0;
+ for (int i : ints) {
+ sum += i;
+ }
+ return sum;
+ }
+
+ private Reader createReader(File folder, FileDataSource fileDataSource) throws FileNotFoundException {
+ return null;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/reflection/ReflectionInstantiator.java b/tests/utils/src/main/java/samples/reflection/ReflectionInstantiator.java
new file mode 100644
index 0000000..4c6d219
--- /dev/null
+++ b/tests/utils/src/main/java/samples/reflection/ReflectionInstantiator.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.reflection;
+
+public class ReflectionInstantiator {
+
+ public boolean instantiateUseMe() throws ClassNotFoundException {
+ Class<?> reflectionClass = Class.forName(
+ "samples.reflection.UseMeInterface", true, Thread
+ .currentThread().getContextClassLoader());
+ return reflectionClass.isAssignableFrom(UseMe.class);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/reflection/UseMe.java b/tests/utils/src/main/java/samples/reflection/UseMe.java
new file mode 100644
index 0000000..16f9c69
--- /dev/null
+++ b/tests/utils/src/main/java/samples/reflection/UseMe.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.reflection;
+
+public class UseMe implements UseMeInterface {
+
+}
diff --git a/tests/utils/src/main/java/samples/reflection/UseMeInterface.java b/tests/utils/src/main/java/samples/reflection/UseMeInterface.java
new file mode 100644
index 0000000..70e00c6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/reflection/UseMeInterface.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2009 the original author or authors.
+
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.reflection;
+
+public interface UseMeInterface {
+
+}
diff --git a/tests/utils/src/main/java/samples/rule/SimpleThing.java b/tests/utils/src/main/java/samples/rule/SimpleThing.java
new file mode 100644
index 0000000..9c55765
--- /dev/null
+++ b/tests/utils/src/main/java/samples/rule/SimpleThing.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.rule;
+
+public interface SimpleThing {
+ String getThingName();
+}
diff --git a/tests/utils/src/main/java/samples/rule/SimpleThingCreator.java b/tests/utils/src/main/java/samples/rule/SimpleThingCreator.java
new file mode 100644
index 0000000..7882ed1
--- /dev/null
+++ b/tests/utils/src/main/java/samples/rule/SimpleThingCreator.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.rule;
+
+public class SimpleThingCreator {
+
+ public static SimpleThing createSimpleThing() {
+ return new SimpleThingImpl();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/rule/SimpleThingImpl.java b/tests/utils/src/main/java/samples/rule/SimpleThingImpl.java
new file mode 100644
index 0000000..1e25c9f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/rule/SimpleThingImpl.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.rule;
+
+public class SimpleThingImpl implements SimpleThing {
+
+ @Override
+ public String getThingName() {
+ return null;
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/rule/ThingToTest.java b/tests/utils/src/main/java/samples/rule/ThingToTest.java
new file mode 100644
index 0000000..df6506a
--- /dev/null
+++ b/tests/utils/src/main/java/samples/rule/ThingToTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.rule;
+
+public class ThingToTest {
+ private final SimpleThing simpleThing;
+
+ public ThingToTest() {
+ simpleThing = SimpleThingCreator.createSimpleThing();
+ }
+
+ public String getName() {
+ // uncomment the line below and the test passes
+ // return simpleThing.getThingName();
+ return "Smith";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/servletmocking/SampleServlet.java b/tests/utils/src/main/java/samples/servletmocking/SampleServlet.java
new file mode 100644
index 0000000..1ed68b7
--- /dev/null
+++ b/tests/utils/src/main/java/samples/servletmocking/SampleServlet.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.servletmocking;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @author volodymyr.tsukur
+ */
+public class SampleServlet extends HttpServlet {
+
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ response.getWriter().write("out");
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/simplemix/SimpleMix.java b/tests/utils/src/main/java/samples/simplemix/SimpleMix.java
new file mode 100644
index 0000000..124ee5b
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplemix/SimpleMix.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.simplemix;
+
+/**
+ * This class is used to demonstrate features such as static, final and partial
+ * mocking as well as access internal state.
+ */
+public class SimpleMix {
+
+ private SimpleMixCollaborator collaborator;
+
+ public final int calculate() {
+ return (SimpleMixUtilities.getRandomInteger() + getValue() - collaborator.getRandomInteger()) * new SimpleMixConstruction().getMyValue();
+ }
+
+ private int getValue() {
+ return (int) (System.currentTimeMillis() / 1000);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/simplemix/SimpleMixCollaborator.java b/tests/utils/src/main/java/samples/simplemix/SimpleMixCollaborator.java
new file mode 100644
index 0000000..0451361
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplemix/SimpleMixCollaborator.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.simplemix;
+
+import java.util.Random;
+
+public final class SimpleMixCollaborator {
+
+ public final int getRandomInteger() {
+ return new Random().nextInt(400);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/simplemix/SimpleMixConstruction.java b/tests/utils/src/main/java/samples/simplemix/SimpleMixConstruction.java
new file mode 100644
index 0000000..5fa33e2
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplemix/SimpleMixConstruction.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.simplemix;
+
+public class SimpleMixConstruction {
+
+ public int getMyValue() {
+ return 4;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/simplemix/SimpleMixUtilities.java b/tests/utils/src/main/java/samples/simplemix/SimpleMixUtilities.java
new file mode 100644
index 0000000..9dc35ea
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplemix/SimpleMixUtilities.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.simplemix;
+
+import java.util.Random;
+
+public class SimpleMixUtilities {
+ public static int getRandomInteger() {
+ return new Random().nextInt();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExample.java b/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExample.java
new file mode 100644
index 0000000..4865d24
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExample.java
@@ -0,0 +1,8 @@
+package samples.simplereturn;
+
+public class SimpleReturnExample {
+
+ public int mySimpleMethod() {
+ return 44;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExampleUser.java b/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExampleUser.java
new file mode 100644
index 0000000..d816759
--- /dev/null
+++ b/tests/utils/src/main/java/samples/simplereturn/SimpleReturnExampleUser.java
@@ -0,0 +1,15 @@
+package samples.simplereturn;
+
+public class SimpleReturnExampleUser {
+
+ private SimpleReturnExample simpleReturnExample;
+
+ public SimpleReturnExampleUser(SimpleReturnExample intReturn2) {
+ super();
+ this.simpleReturnExample = intReturn2;
+ }
+
+ public int myMethod() {
+ return simpleReturnExample.mySimpleMethod();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/singleton/SimpleStaticService.java b/tests/utils/src/main/java/samples/singleton/SimpleStaticService.java
new file mode 100644
index 0000000..4147ce8
--- /dev/null
+++ b/tests/utils/src/main/java/samples/singleton/SimpleStaticService.java
@@ -0,0 +1,8 @@
+package samples.singleton;
+
+public class SimpleStaticService {
+
+ public static String say(final String string) {
+ return "Hello " + string;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/singleton/StaticExample.java b/tests/utils/src/main/java/samples/singleton/StaticExample.java
new file mode 100644
index 0000000..8f7e561
--- /dev/null
+++ b/tests/utils/src/main/java/samples/singleton/StaticExample.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.singleton;
+
+/**
+ *Can be used to assert that partial mocking of static methods works.
+ */
+public class StaticExample {
+
+ public static void voidMethod() {
+ privateVoidMethod();
+ }
+
+ private static void privateVoidMethod() {
+ }
+
+ public static void voidFinalMethod() {
+ privateVoidFinalMethod();
+ }
+
+ private static final void privateVoidFinalMethod() {
+ }
+
+ public static void staticVoidMethod() {
+ throw new IllegalArgumentException("This should never happen");
+ }
+
+ public static String staticMethodReturningString() {
+ throw new IllegalArgumentException("This should never happen");
+ }
+
+ public static final void staticFinalVoidMethod() {
+ throw new IllegalArgumentException("This should never happen");
+ }
+
+ public static Object objectMethod() {
+ return privateObjectMethod();
+ }
+
+ private static Object privateObjectMethod() {
+ return new Object();
+ }
+
+ public static Object objectFinalMethod() {
+ return privateObjectFinalMethod();
+ }
+
+ private static final Object privateObjectFinalMethod() {
+ return new Object();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/singleton/StaticHelper.java b/tests/utils/src/main/java/samples/singleton/StaticHelper.java
new file mode 100644
index 0000000..fdedf0c
--- /dev/null
+++ b/tests/utils/src/main/java/samples/singleton/StaticHelper.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.singleton;
+
+public class StaticHelper {
+
+ public static void sayHelloHelper() {
+ System.out.println("hello");
+ }
+
+ public static void sayHelloAgain() {
+ System.out.println("hello");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/singleton/StaticService.java b/tests/utils/src/main/java/samples/singleton/StaticService.java
new file mode 100644
index 0000000..a3b9a9a
--- /dev/null
+++ b/tests/utils/src/main/java/samples/singleton/StaticService.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.singleton;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Test class to demonstrate static, static+final, static+native and
+ * static+final+native methods mocking.
+ *
+ * @author Johan Haleby
+ * @author Jan Kronquist
+ */
+public class StaticService {
+
+ private static int number = 17;
+ private static Integer intValue;
+ public static String messageStorage;
+
+ private int secret = 23;
+
+ public static void sayHello(String message) {
+ messageStorage = message;
+ }
+
+ public static void sayHello(Integer intValue) {
+ StaticService.intValue = intValue;
+ }
+
+ public static int getNumberFromInner() {
+ return new Callable<Integer>() {
+ @Override
+ public Integer call() {
+ return number;
+ }
+ }.call();
+ }
+
+ public static int getNumberFromInnerInstance() {
+ return new StaticService().internalGetNumberFromInnerInstance();
+ }
+
+ public int internalGetNumberFromInnerInstance() {
+ return new Callable<Integer>() {
+ @Override
+ public Integer call() {
+ return secret;
+ }
+ }.call();
+ }
+
+ public static String doStatic(int i) {
+ throw new UnsupportedOperationException("method not implemented yet...");
+ }
+
+ public static void assertThatVerifyWorksForMultipleMocks() {
+ StaticService.sayHello();
+ StaticHelper.sayHelloHelper();
+ }
+
+ public static void sayHello() {
+ StaticHelper.sayHelloHelper();
+ StaticHelper.sayHelloHelper();
+ }
+
+ public static void sayHelloAgain() {
+ StaticHelper.sayHelloAgain();
+ StaticHelper.sayHelloAgain();
+ }
+
+ public static String say(String string) {
+ return "Hello " + string;
+ }
+
+ public final static String sayFinal(String string) {
+ return "Hello " + string;
+ }
+
+ public native static String sayNative(String string);
+
+ public final native static String sayFinalNative(String string);
+
+ public static int calculate(int a, int b) {
+ return a + b;
+ }
+
+ private static String sayPrivateStatic(String string) {
+ return "Hello private static " + string;
+ }
+
+ private static String sayPrivateFinalStatic(String string) {
+ return "Hello private static " + string;
+ }
+
+ private static final native String sayPrivateNativeFinalStatic(String string);
+}
diff --git a/tests/utils/src/main/java/samples/singleton/StaticWithPrivateCtor.java b/tests/utils/src/main/java/samples/singleton/StaticWithPrivateCtor.java
new file mode 100644
index 0000000..7a74237
--- /dev/null
+++ b/tests/utils/src/main/java/samples/singleton/StaticWithPrivateCtor.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.singleton;
+
+public class StaticWithPrivateCtor {
+
+ private StaticWithPrivateCtor(){
+ }
+
+ public static String staticMethod() {
+ return "something";
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/spy/SpyObject.java b/tests/utils/src/main/java/samples/spy/SpyObject.java
new file mode 100644
index 0000000..f45afcd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/spy/SpyObject.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2013 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.spy;
+
+public class SpyObject {
+
+ public String getMyString() {
+ return "something";
+ }
+
+ public String getStringTwo() {
+ return "two";
+ }
+
+
+ public void throwException() {
+ throw new RuntimeException("Aaaaa! Test is failed.");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceDemo.java b/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceDemo.java
new file mode 100644
index 0000000..7c7493d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceDemo.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticandinstance;
+
+/**
+ * Demonstrates how to mock both instance and static methods in the same test
+ *
+ * @author Johan Haleby
+ */
+public class StaticAndInstanceDemo {
+
+ public String getMessage() {
+ return getPrivateMessage() + StaticAndInstanceDemo.getStaticMessage();
+ }
+
+ private String getPrivateMessage() {
+ return "Private ";
+ }
+
+ public static final String getStaticMessage() {
+ return "hello world!";
+ }
+
+ public static void aVoidMethod() {
+ }
+
+ public static Object aMethod2(String aString) {
+ return null;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceWithConstructorCodeDemo.java b/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceWithConstructorCodeDemo.java
new file mode 100644
index 0000000..891527f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticandinstance/StaticAndInstanceWithConstructorCodeDemo.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticandinstance;
+
+/**
+ * The purpose of this class is to be used to verify that the
+ * http://code.google.com/p/powermock/issues/detail?id=4 is fixed.
+ *
+ */
+public class StaticAndInstanceWithConstructorCodeDemo {
+
+ private final StaticAndInstanceDemo staticAndInstanceDemo;
+
+ public StaticAndInstanceWithConstructorCodeDemo(
+ StaticAndInstanceDemo staticAndInstanceDemo) {
+ this.staticAndInstanceDemo = staticAndInstanceDemo;
+ }
+
+ public String getMessage() {
+ return StaticAndInstanceDemo.getStaticMessage()
+ + staticAndInstanceDemo.getMessage();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticinitializer/AbstractStaticInitializerExample.java b/tests/utils/src/main/java/samples/staticinitializer/AbstractStaticInitializerExample.java
new file mode 100644
index 0000000..9119f03
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticinitializer/AbstractStaticInitializerExample.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticinitializer;
+
+public abstract class AbstractStaticInitializerExample {
+
+
+ static {
+ if (true) {
+ throw new RuntimeException("This code must be suppressed!");
+ }
+ }
+
+ public static String getStaticString() {
+ return "something";
+ }
+
+ public String getString() {
+ return "something";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticinitializer/EvilStaticInitializerExample.java b/tests/utils/src/main/java/samples/staticinitializer/EvilStaticInitializerExample.java
new file mode 100644
index 0000000..a1c70dd
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticinitializer/EvilStaticInitializerExample.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticinitializer;
+
+/**
+ * Simple example of a class with a static initializer.
+ */
+public class EvilStaticInitializerExample {
+
+ public static final String FAILED_TO_LOAD_LIBRARY_MESSAGE = "Failed to load a required dll, please make sure that you've installed the software correctly";
+
+ static {
+ try {
+ System.loadLibrary("path/to/mylibrary.dll");
+ } catch (UnsatisfiedLinkError error) {
+ throw new UnsatisfiedLinkError(FAILED_TO_LOAD_LIBRARY_MESSAGE);
+ }
+ }
+
+ /*
+ * We imagine that this method require the library to execute, but we want
+ * to test it anyway in separation.
+ */
+ public String doSomeNativeStuffUsingTheLoadedSystemLibrary() {
+ return "native stuff";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticinitializer/InterfaceComputation.java b/tests/utils/src/main/java/samples/staticinitializer/InterfaceComputation.java
new file mode 100644
index 0000000..53fc74b
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticinitializer/InterfaceComputation.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticinitializer;
+
+interface InterfaceA
+{
+ public static final int A = 2 * InterfaceB.B;
+// public void methodA();
+} // End of interface
+interface InterfaceB
+{
+ public static final int B = InterfaceC.C + 1;
+// public String methodB(int qwe);
+} // End of interface
+interface InterfaceC extends InterfaceA
+{
+ public static final int C = A + 1;
+} // End of interface
+
+public class InterfaceComputation implements InterfaceA, InterfaceB, InterfaceC
+{
+ public static void main(String[] args) {
+ System.out.println(calculateWithinHierarchy());
+ }
+ public static int calculateWithinHierarchy() {
+ return C + B + A;
+ }
+ public static int calculateWithReference() {
+ return InterfaceC.C + InterfaceB.B + InterfaceA.A;
+ }
+
+// public void methodA() {
+// }
+//
+// public String methodB(int qwe) {
+// return "";
+// }
+} // End of class
diff --git a/tests/utils/src/main/java/samples/staticinitializer/SimpleStaticInitializerExample.java b/tests/utils/src/main/java/samples/staticinitializer/SimpleStaticInitializerExample.java
new file mode 100644
index 0000000..0a05c90
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticinitializer/SimpleStaticInitializerExample.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticinitializer;
+
+public class SimpleStaticInitializerExample {
+
+ private static final String string;
+
+ static {
+ string = "static world!";
+ }
+
+ public String getString() {
+ return string;
+ }
+
+ public final String getConcatenatedString(String concat) {
+ return concat + " " + string;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/staticinitializer/StaticInitializerExample.java b/tests/utils/src/main/java/samples/staticinitializer/StaticInitializerExample.java
new file mode 100644
index 0000000..f6a7f2f
--- /dev/null
+++ b/tests/utils/src/main/java/samples/staticinitializer/StaticInitializerExample.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.staticinitializer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class StaticInitializerExample {
+
+ private static final Set<String> mySet;
+
+ static {
+ mySet = new HashSet<String>();
+ if (true) {
+ throw new RuntimeException("This code must be suppressed!");
+ }
+ }
+
+ public static Set<String> getMySet() {
+ return mySet;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/stress/ClassWithStatic.java b/tests/utils/src/main/java/samples/stress/ClassWithStatic.java
new file mode 100644
index 0000000..9794742
--- /dev/null
+++ b/tests/utils/src/main/java/samples/stress/ClassWithStatic.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.stress;
+
+public class ClassWithStatic {
+
+ public static String a(){
+ return "str";
+ }
+ public static String b(){
+ return "str";
+ }
+ public static String c(){
+ return "str";
+ }
+ public static String d(){
+ return "str";
+ }
+ public static String e(){
+ return "str";
+ }
+ public static String f(){
+ return "str";
+ }
+ public static String g(){
+ return "str";
+ }
+ public static String h(){
+ return "str";
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/src/main/java/samples/stress/StressSample.java b/tests/utils/src/main/java/samples/stress/StressSample.java
new file mode 100644
index 0000000..0114913
--- /dev/null
+++ b/tests/utils/src/main/java/samples/stress/StressSample.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.stress;
+
+public class StressSample {
+ public String a1(){
+ return ClassWithStatic.a();
+ }
+ public String b1(){
+ return ClassWithStatic.b();
+ }
+ public String c1(){
+ return ClassWithStatic.c();
+ }
+ public String d1(){
+ return ClassWithStatic.d();
+ }
+ public String e1(){
+ return ClassWithStatic.e();
+ }
+ public String f1(){
+ return ClassWithStatic.f();
+ }
+ public String g1(){
+ return ClassWithStatic.g();
+ }
+ public String h1(){
+ return ClassWithStatic.h();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/strict/StrictDemo.java b/tests/utils/src/main/java/samples/strict/StrictDemo.java
new file mode 100644
index 0000000..b01abdb
--- /dev/null
+++ b/tests/utils/src/main/java/samples/strict/StrictDemo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.strict;
+
+public class StrictDemo {
+
+ public void callAThenB() {
+ A();
+ B();
+ }
+
+ private void A() {
+ // Does nothing
+ }
+
+ private void B() {
+ // Does nothing
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/AppaleList.java b/tests/utils/src/main/java/samples/suppressconstructor/AppaleList.java
new file mode 100644
index 0000000..a27a644
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/AppaleList.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.suppressconstructor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AppaleList {
+
+ public AppaleList() {
+ throw new IllegalArgumentException("Shouldn't be called");
+ }
+
+ public AppaleList(String str) {
+ throw new IllegalArgumentException("Shouldn't be called");
+ }
+
+ public String getAll() {
+ List<String> list = new ArrayList<String>();
+ list.add("sb1");
+ List<String> list1 = new ArrayList<String>(10);
+ list1.add("sb2");
+ list1.add("sb3");
+ list1.add("sb4");
+ return "str";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/InvokeConstructor.java b/tests/utils/src/main/java/samples/suppressconstructor/InvokeConstructor.java
new file mode 100644
index 0000000..39b09ca
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/InvokeConstructor.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class InvokeConstructor {
+
+ public String doStuff(String m) {
+ return new SuppressConstructorHierarchy(m).getMessage();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorDemo.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorDemo.java
new file mode 100644
index 0000000..0f4bb17
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorDemo.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressConstructorDemo extends
+ SuppressConstructorSubclassDemo {
+
+ public SuppressConstructorDemo(String message) {
+ super(message);
+ }
+
+ public String getMyOwnMessage() {
+ return returnAMessage();
+ }
+
+ private String returnAMessage() {
+ return "my message";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHeirarchyEvilGrandParent.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHeirarchyEvilGrandParent.java
new file mode 100644
index 0000000..b50afae
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHeirarchyEvilGrandParent.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressConstructorHeirarchyEvilGrandParent {
+
+ SuppressConstructorHeirarchyEvilGrandParent() {
+ throw new RuntimeException("This should be suppressed!!");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchy.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchy.java
new file mode 100644
index 0000000..8661748
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchy.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressConstructorHierarchy extends SuppressConstructorHierarchyParent {
+
+ public SuppressConstructorHierarchy(String message) {
+ super(message);
+ }
+
+ /**
+ * This method is just here to check if it works to execute several tests
+ * with the same test suite class loader.
+ *
+ * @return 42.
+ */
+ public int getNumber() {
+ return 42;
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchyParent.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchyParent.java
new file mode 100644
index 0000000..af76f6e
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorHierarchyParent.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressConstructorHierarchyParent extends
+ SuppressConstructorHeirarchyEvilGrandParent {
+
+ private String message;
+
+ SuppressConstructorHierarchyParent() {
+ System.out.println("Parent constructor");
+ this.message = "Default message";
+ }
+
+ SuppressConstructorHierarchyParent(String message) {
+ System.out.println("Parent constructor with message");
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorSubclassDemo.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorSubclassDemo.java
new file mode 100644
index 0000000..9a35059
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressConstructorSubclassDemo.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressConstructorSubclassDemo {
+
+ private String message;
+
+ SuppressConstructorSubclassDemo(String message) {
+ this.message = message;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressNonParentConstructorDemo.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressNonParentConstructorDemo.java
new file mode 100644
index 0000000..e5823be
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressNonParentConstructorDemo.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressNonParentConstructorDemo {
+
+ public SuppressNonParentConstructorDemo(String message) {
+ throw new IllegalStateException(message);
+ }
+
+ public String getHello() {
+ return "Hello";
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/suppressconstructor/SuppressSpecificConstructorDemo.java b/tests/utils/src/main/java/samples/suppressconstructor/SuppressSpecificConstructorDemo.java
new file mode 100644
index 0000000..9fbd7a1
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressconstructor/SuppressSpecificConstructorDemo.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressconstructor;
+
+public class SuppressSpecificConstructorDemo {
+
+ public SuppressSpecificConstructorDemo() {
+ throw new IllegalStateException(
+ "This constructor should not be suppress");
+ }
+
+ public SuppressSpecificConstructorDemo(String message) {
+ throw new IllegalStateException(message);
+ }
+
+ public String getHello() {
+ return "Hello";
+ }
+
+}
diff --git a/tests/utils/src/main/java/samples/suppresseverything/SuppressEverything.java b/tests/utils/src/main/java/samples/suppresseverything/SuppressEverything.java
new file mode 100644
index 0000000..1c495ce
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppresseverything/SuppressEverything.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2010 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppresseverything;
+
+public class SuppressEverything {
+
+ public SuppressEverything() {
+ throw new IllegalStateException("error");
+ }
+
+ public SuppressEverything(String string) {
+ throw new IllegalStateException("error");
+ }
+
+ public int something() {
+ throw new IllegalStateException("error");
+ }
+
+ public void somethingElse() {
+ throw new IllegalStateException("error");
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressfield/DomainObject.java b/tests/utils/src/main/java/samples/suppressfield/DomainObject.java
new file mode 100644
index 0000000..baf104c
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressfield/DomainObject.java
@@ -0,0 +1,7 @@
+package samples.suppressfield;
+
+public class DomainObject {
+
+ public DomainObject() {
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressfield/ItemRepository.java b/tests/utils/src/main/java/samples/suppressfield/ItemRepository.java
new file mode 100644
index 0000000..f3474f6
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressfield/ItemRepository.java
@@ -0,0 +1,30 @@
+package samples.suppressfield;
+
+import java.util.HashMap;
+
+public class ItemRepository {
+ private static HashMap<String, String> itemMap = new HashMap<String, String>();
+
+ @SuppressWarnings("unused")
+ private MyClass myClass = new MyClass();
+
+ private int totalItems = 0;
+
+ public void addItem(String key, String value) {
+ itemMap.put(key, value);
+ totalItems++;
+ }
+
+ public void delItem(String key) {
+ if (itemMap.containsKey(key)) {
+ itemMap.remove(key);
+ totalItems--;
+ }
+ }
+
+ private static class MyClass {
+ public MyClass() {
+ throw new IllegalArgumentException("Constructor should never be called during this test");
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/utils/src/main/java/samples/suppressfield/SuppressField.java b/tests/utils/src/main/java/samples/suppressfield/SuppressField.java
new file mode 100644
index 0000000..086a458
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressfield/SuppressField.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressfield;
+
+public class SuppressField {
+
+ private static final int MY_VALUE = 8;
+
+ private static final Object MY_OBJECT = new Object();
+
+ private final boolean myBoolean = true;
+
+ private final Boolean myWrappedBoolean = Boolean.TRUE;
+
+ private final Object mySecondValue = new Object();
+
+ private DomainObject domainObject = new DomainObject();
+
+ public Object getMySecondValue() {
+ return mySecondValue;
+ }
+
+ public DomainObject getDomainObject() {
+ return domainObject;
+ }
+
+ private char myChar = 'a';
+
+ public static int getMyValue() {
+ return MY_VALUE;
+ }
+
+ public static Object getMyObject() {
+ return MY_OBJECT;
+ }
+
+ public boolean isMyBoolean() {
+ return myBoolean;
+ }
+
+ public Boolean getMyWrappedBoolean() {
+ return myWrappedBoolean;
+ }
+
+ public char getMyChar() {
+ return myChar;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressmethod/SuppressMethod.java b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethod.java
new file mode 100644
index 0000000..9a8a815
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethod.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressmethod;
+
+public class SuppressMethod extends SuppressMethodParent {
+
+ public static final Object OBJECT = new Object();
+
+ public Object getObjectWithArgument(String argument) {
+ return OBJECT;
+ }
+
+ public Object getObject() {
+ return OBJECT;
+ }
+
+ public static Object getObjectStatic() {
+ return OBJECT;
+ }
+
+ public byte getByte() {
+ return Byte.MAX_VALUE;
+ }
+
+ public short getShort() {
+ return Short.MAX_VALUE;
+ }
+
+ public int getInt() {
+ return Integer.MAX_VALUE;
+ }
+
+ public long getLong() {
+ return Long.MAX_VALUE;
+ }
+
+ public boolean getBoolean() {
+ return true;
+ }
+
+ public float getFloat() {
+ return Float.MAX_VALUE;
+ }
+
+ public double getDouble() {
+ return Double.MAX_VALUE;
+ }
+
+ public double getDouble(double value) {
+ return value;
+ }
+
+ public void invokeVoid(StringBuilder s) {
+ s.append("This should be suppressed!");
+ }
+
+ @Override
+ public int myMethod() {
+ return 20 + super.myMethod();
+ }
+
+ public Object sameName(int i) {
+ return OBJECT;
+ }
+
+ public Object sameName(float f) {
+ return OBJECT;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodExample.java b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodExample.java
new file mode 100644
index 0000000..5c1f200
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodExample.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.suppressmethod;
+
+public class SuppressMethodExample extends SuppressMethodParent {
+
+ public static final Object OBJECT = new Object();
+
+ public Object getObject() {
+ return OBJECT;
+ }
+
+ public Object getStringObject() {
+ return "test";
+ }
+
+ public static Object getStringObjectStatic() {
+ return "test";
+ }
+}
diff --git a/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodParent.java b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodParent.java
new file mode 100644
index 0000000..a6bbc07
--- /dev/null
+++ b/tests/utils/src/main/java/samples/suppressmethod/SuppressMethodParent.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package samples.suppressmethod;
+
+public abstract class SuppressMethodParent {
+
+ public int myMethod() {
+ return 42;
+ }
+}
diff --git a/tests/utils/src/main/java/samples/swing/ReallySimpleSwingDemo.java b/tests/utils/src/main/java/samples/swing/ReallySimpleSwingDemo.java
new file mode 100644
index 0000000..1ce2d00
--- /dev/null
+++ b/tests/utils/src/main/java/samples/swing/ReallySimpleSwingDemo.java
@@ -0,0 +1,10 @@
+package samples.swing;
+
+import javax.swing.*;
+
+public class ReallySimpleSwingDemo {
+
+ public void displayMessage(String message) {
+ JOptionPane.showMessageDialog(null, message);
+ }
+}
diff --git a/tests/utils/src/main/java/samples/swing/SimpleSwingDemo.java b/tests/utils/src/main/java/samples/swing/SimpleSwingDemo.java
new file mode 100644
index 0000000..a073b1d
--- /dev/null
+++ b/tests/utils/src/main/java/samples/swing/SimpleSwingDemo.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.swing;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * A basic swing application example.
+ *
+ * @author Johan Haleby
+ */
+public class SimpleSwingDemo extends JFrame {
+
+ private static final long serialVersionUID = -190175253588111657L;
+
+ public SimpleSwingDemo() {
+ initialize();
+ }
+
+ private void initialize() {
+ setLayout(new FlowLayout());
+ final JLabel jlbHelloWorld = new JLabel("Hello World!");
+ JButton jButton = new JButton("Click Me!");
+
+ jButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent actionevent) {
+ jlbHelloWorld.setText("Clicked on button");
+ }
+ });
+
+ add(jlbHelloWorld);
+ add(jButton);
+ setSize(100, 100);
+ setVisible(true);
+ }
+
+ public static void main(String[] args) {
+ new SimpleSwingDemo();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/system/SystemClassUser.java b/tests/utils/src/main/java/samples/system/SystemClassUser.java
new file mode 100644
index 0000000..69291ca
--- /dev/null
+++ b/tests/utils/src/main/java/samples/system/SystemClassUser.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.system;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.*;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Class used to demonstrate PowerMock's ability to mock system classes.
+ */
+public class SystemClassUser {
+
+ public void threadSleep() throws InterruptedException {
+ Thread.sleep(5000);
+ }
+
+ public String performEncode() throws UnsupportedEncodingException {
+ return URLEncoder.encode("string", "enc");
+ }
+
+ public Process executeCommand() throws IOException {
+ return Runtime.getRuntime().exec("command");
+ }
+
+ public String getSystemProperty() throws IOException {
+ return System.getProperty("property");
+ }
+
+ public void doMoreComplicatedStuff() throws IOException {
+ System.setProperty("nanoTime", Long.toString(System.nanoTime()));
+ }
+
+ public void copyProperty(String to, String from) throws IOException {
+ System.setProperty(to, System.getProperty(from));
+ }
+
+ public String format(String one, String args) throws IOException {
+ return String.format(one, args);
+ }
+
+ public URL newURL(String anUrl) throws MalformedURLException {
+ return new URL(anUrl);
+ }
+
+ public StringBuilder newStringBuilder() {
+ return new StringBuilder();
+ }
+
+ public void shuffleCollection(List<?> list) {
+ Collections.shuffle(list);
+ }
+
+ public URLConnection useURL(URL url) throws IOException {
+ return url.openConnection();
+ }
+
+ public InetAddress getLocalHost() throws IOException {
+ return InetAddress.getLocalHost();
+ }
+
+ public String generatePerishableToken() {
+ final UUID uuid = UUID.randomUUID();
+ final String toString = uuid.toString();
+ final String result = toString.replaceAll("-", "");
+ return result;
+ }
+
+ public int lengthOf(StringBuilder to){
+ // The trick here is the casting to CharSequence,
+ // this is to test that the runtime type(StringBuilder) is checked for mocked calls and not
+ // the compile-time type (CharSequence)
+ return lengthOf((CharSequence) to);
+ }
+
+ private int lengthOf(CharSequence to){
+ return to.length();
+ }
+}
diff --git a/tests/utils/src/main/java/samples/whitebox/ClassWithPowerMockGeneratedConstructor.java b/tests/utils/src/main/java/samples/whitebox/ClassWithPowerMockGeneratedConstructor.java
new file mode 100644
index 0000000..af4ff55
--- /dev/null
+++ b/tests/utils/src/main/java/samples/whitebox/ClassWithPowerMockGeneratedConstructor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package samples.whitebox;
+
+import org.powermock.core.IndicateReloadClass;
+
+/**
+ * Class that simulates a PowerMock generated constructor.
+ */
+public class ClassWithPowerMockGeneratedConstructor {
+ public ClassWithPowerMockGeneratedConstructor(String string) {
+ }
+
+ /**
+ * Simulates a PowerMock generated constructor.
+ */
+ public ClassWithPowerMockGeneratedConstructor(IndicateReloadClass indicateReloadClass) {
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/powermock.git
More information about the pkg-java-commits
mailing list